Rizin
unix-like reverse engineering framework and cli tools
signals.c
Go to the documentation of this file.
1
//
5
//
6
// Author: Lasse Collin
7
//
8
// This file has been put into the public domain.
9
// You can do whatever you want with this file.
10
//
12
13
#include "
private.h
"
14
15
16
volatile
sig_atomic_t
user_abort
=
false
;
17
18
19
#if !(defined(_WIN32) && !defined(__CYGWIN__))
20
24
static
volatile
sig_atomic_t
exit_signal
= 0;
25
28
static
sigset_t
hooked_signals
;
29
33
static
bool
signals_are_initialized
=
false
;
34
36
static
size_t
signals_block_count
= 0;
37
38
39
static
void
40
signal_handler
(
int
sig)
41
{
42
exit_signal
= sig;
43
user_abort
=
true
;
44
45
#ifndef TUKLIB_DOSLIKE
46
io_write_to_user_abort_pipe
();
47
#endif
48
49
return
;
50
}
51
52
53
extern
void
54
signals_init
(
void
)
55
{
56
// List of signals for which we establish the signal handler.
57
static
const
int
sigs[] = {
58
SIGINT,
59
SIGTERM,
60
#ifdef SIGHUP
61
SIGHUP
,
62
#endif
63
#ifdef SIGPIPE
64
SIGPIPE,
65
#endif
66
#ifdef SIGXCPU
67
SIGXCPU,
68
#endif
69
#ifdef SIGXFSZ
70
SIGXFSZ,
71
#endif
72
};
73
74
// Mask of the signals for which we have established a signal handler.
75
sigemptyset(&
hooked_signals
);
76
for
(
size_t
i
= 0;
i
<
ARRAY_SIZE
(sigs); ++
i
)
77
sigaddset(&
hooked_signals
, sigs[
i
]);
78
79
#ifdef SIGALRM
80
// Add also the signals from message.c to hooked_signals.
81
for
(
size_t
i
= 0;
message_progress_sigs
[
i
] != 0; ++
i
)
82
sigaddset(&
hooked_signals
,
message_progress_sigs
[
i
]);
83
#endif
84
85
// Using "my_sa" because "sa" may conflict with a sockaddr variable
86
// from system headers on Solaris.
87
struct
sigaction my_sa;
88
89
// All the signals that we handle we also blocked while the signal
90
// handler runs.
91
my_sa.sa_mask =
hooked_signals
;
92
93
// Don't set SA_RESTART, because we want EINTR so that we can check
94
// for user_abort and cleanup before exiting. We block the signals
95
// for which we have established a handler when we don't want EINTR.
96
my_sa.sa_flags = 0;
97
my_sa.sa_handler = &
signal_handler
;
98
99
for
(
size_t
i
= 0;
i
<
ARRAY_SIZE
(sigs); ++
i
) {
100
// If the parent process has left some signals ignored,
101
// we don't unignore them.
102
struct
sigaction old;
103
if
(sigaction(sigs[
i
],
NULL
, &old) == 0
104
&& old.sa_handler == SIG_IGN)
105
continue
;
106
107
// Establish the signal handler.
108
if
(sigaction(sigs[
i
], &my_sa,
NULL
))
109
message_signal_handler
();
110
}
111
112
signals_are_initialized
=
true
;
113
114
return
;
115
}
116
117
118
#ifndef __VMS
119
extern
void
120
signals_block
(
void
)
121
{
122
if
(
signals_are_initialized
) {
123
if
(
signals_block_count
++ == 0) {
124
const
int
saved_errno = errno;
125
mythread_sigmask
(SIG_BLOCK, &
hooked_signals
,
NULL
);
126
errno = saved_errno;
127
}
128
}
129
130
return
;
131
}
132
133
134
extern
void
135
signals_unblock
(
void
)
136
{
137
if
(
signals_are_initialized
) {
138
assert
(
signals_block_count
> 0);
139
140
if
(--
signals_block_count
== 0) {
141
const
int
saved_errno = errno;
142
mythread_sigmask
(SIG_UNBLOCK, &
hooked_signals
,
NULL
);
143
errno = saved_errno;
144
}
145
}
146
147
return
;
148
}
149
#endif
150
151
152
extern
void
153
signals_exit
(
void
)
154
{
155
const
int
sig = (
int
)
exit_signal
;
156
157
if
(sig != 0) {
158
#if defined(TUKLIB_DOSLIKE) || defined(__VMS)
159
// Don't raise(), set only exit status. This avoids
160
// printing unwanted message about SIGINT when the user
161
// presses C-c.
162
set_exit_status
(
E_ERROR
);
163
#else
164
struct
sigaction sa;
165
sa.sa_handler = SIG_DFL;
166
sigfillset(&sa.sa_mask);
167
sa.sa_flags = 0;
168
sigaction(sig, &sa,
NULL
);
169
raise
(sig);
170
#endif
171
}
172
173
return
;
174
}
175
176
#else
177
178
// While Windows has some very basic signal handling functions as required
179
// by C89, they are not really used, and e.g. SIGINT doesn't work exactly
180
// the way it does on POSIX (Windows creates a new thread for the signal
181
// handler). Instead, we use SetConsoleCtrlHandler() to catch user
182
// pressing C-c, because that seems to be the recommended way to do it.
183
//
184
// NOTE: This doesn't work under MSYS. Trying with SIGINT doesn't work
185
// either even if it appeared to work at first. So test using Windows
186
// console window.
187
188
static
BOOL WINAPI
189
signal_handler
(
DWORD
type
lzma_attribute
((__unused__)))
190
{
191
// Since we don't get a signal number which we could raise() at
192
// signals_exit() like on POSIX, just set the exit status to
193
// indicate an error, so that we cannot return with zero exit status.
194
set_exit_status
(
E_ERROR
);
195
user_abort
=
true
;
196
return
TRUE
;
197
}
198
199
200
extern
void
201
signals_init
(
void
)
202
{
203
if
(!SetConsoleCtrlHandler(&
signal_handler
,
TRUE
))
204
message_signal_handler
();
205
206
return
;
207
}
208
209
#endif
ARRAY_SIZE
#define ARRAY_SIZE(a)
Definition:
analysis_riscv.c:11
i
lzma_index ** i
Definition:
index.h:629
NULL
#define NULL
Definition:
cris-opc.c:27
io_write_to_user_abort_pipe
void io_write_to_user_abort_pipe(void)
Write a byte to user_abort_pipe[1].
Definition:
file_io.c:135
lzma_attribute
#define lzma_attribute(attr)
Definition:
lzma.h:259
assert
assert(limit<=UINT32_MAX/2)
message_signal_handler
void message_signal_handler(void)
Definition:
message.c:796
message_progress_sigs
const int message_progress_sigs[]
Signals used for progress message handling.
type
int type
Definition:
mipsasm.c:17
TRUE
#define TRUE
Definition:
mybfd.h:103
mythread_sigmask
static void mythread_sigmask(int how, const sigset_t *restrict set, sigset_t *restrict oset)
Definition:
mythread.h:87
int
static int
Definition:
sfsocketcall.h:114
sigset_t
int sigset_t
Definition:
sftypes.h:63
user_abort
volatile sig_atomic_t user_abort
Definition:
signals.c:16
signals_block_count
static size_t signals_block_count
signals_block() and signals_unblock() can be called recursively.
Definition:
signals.c:36
exit_signal
static volatile sig_atomic_t exit_signal
Definition:
signals.c:24
signals_init
void signals_init(void)
Definition:
signals.c:54
signals_are_initialized
static bool signals_are_initialized
Definition:
signals.c:33
signals_unblock
void signals_unblock(void)
Unblock the signals blocked by signals_block().
Definition:
signals.c:135
signals_block
void signals_block(void)
Definition:
signals.c:120
signals_exit
void signals_exit(void)
Definition:
signals.c:153
hooked_signals
static sigset_t hooked_signals
Definition:
signals.c:28
signal_handler
static void signal_handler(int sig)
Definition:
signals.c:40
set_exit_status
void set_exit_status(enum exit_status_type new_status)
Definition:
main.c:31
private.h
Common includes, definitions, and prototypes.
E_ERROR
@ E_ERROR
Definition:
transport.h:23
SIGHUP
#define SIGHUP
Definition:
win.h:86
DWORD
DWORD
Definition:
windows_debug.h:119
subprojects
xz-5.2.5
src
xz
signals.c
Generated by
1.9.1