1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
6 #include "errno-util.h"
7 #include "missing_syscall.h"
8 #include "parse-util.h"
9 #include "signal-util.h"
10 #include "stdio-util.h"
11 #include "string-table.h"
12 #include "string-util.h"
14 int reset_all_signal_handlers(void) {
17 for (int sig
= 1; sig
< _NSIG
; sig
++) {
19 /* These two cannot be caught... */
20 if (IN_SET(sig
, SIGKILL
, SIGSTOP
))
23 /* On Linux the first two RT signals are reserved by glibc, and sigaction() will return
25 r
= RET_NERRNO(sigaction(sig
, &sigaction_default
, NULL
));
33 int reset_signal_mask(void) {
36 if (sigemptyset(&ss
) < 0)
39 return RET_NERRNO(sigprocmask(SIG_SETMASK
, &ss
, NULL
));
42 int sigaction_many_internal(const struct sigaction
*sa
, ...) {
48 /* negative signal ends the list. 0 signal is skipped. */
49 while ((sig
= va_arg(ap
, int)) >= 0) {
54 RET_GATHER(r
, RET_NERRNO(sigaction(sig
, sa
, NULL
)));
62 static int sigset_add_many_ap(sigset_t
*ss
, va_list ap
) {
67 while ((sig
= va_arg(ap
, int)) >= 0) {
72 if (sigaddset(ss
, sig
) < 0) {
81 int sigset_add_many_internal(sigset_t
*ss
, ...) {
86 r
= sigset_add_many_ap(ss
, ap
);
92 int sigprocmask_many_internal(int how
, sigset_t
*old
, ...) {
97 if (sigemptyset(&ss
) < 0)
101 r
= sigset_add_many_ap(&ss
, ap
);
107 return RET_NERRNO(sigprocmask(how
, &ss
, old
));
110 static const char *const static_signal_table
[] = {
127 [SIGSTKFLT
] = "STKFLT", /* Linux on SPARC doesn't know SIGSTKFLT */
138 [SIGVTALRM
] = "VTALRM",
140 [SIGWINCH
] = "WINCH",
146 DEFINE_PRIVATE_STRING_TABLE_LOOKUP(static_signal
, int);
148 const char* signal_to_string(int signo
) {
149 static thread_local
char buf
[STRLEN("RTMIN+") + DECIMAL_STR_MAX(int)];
152 name
= static_signal_to_string(signo
);
156 if (signo
>= SIGRTMIN
&& signo
<= SIGRTMAX
)
157 xsprintf(buf
, "RTMIN+%d", signo
- SIGRTMIN
);
159 xsprintf(buf
, "%d", signo
);
164 int signal_from_string(const char *s
) {
168 /* Check that the input is a signal number. */
169 if (safe_atoi(s
, &signo
) >= 0) {
170 if (SIGNAL_VALID(signo
))
176 /* Drop "SIG" prefix. */
177 if (startswith(s
, "SIG"))
180 /* Check that the input is a signal name. */
181 signo
= static_signal_from_string(s
);
185 /* Check that the input is RTMIN or
186 * RTMIN+n (0 <= n <= SIGRTMAX-SIGRTMIN). */
187 p
= startswith(s
, "RTMIN");
194 r
= safe_atoi(p
, &signo
);
198 if (signo
< 0 || signo
> SIGRTMAX
- SIGRTMIN
)
201 return signo
+ SIGRTMIN
;
204 /* Check that the input is RTMAX or
205 * RTMAX-n (0 <= n <= SIGRTMAX-SIGRTMIN). */
206 p
= startswith(s
, "RTMAX");
213 r
= safe_atoi(p
, &signo
);
217 if (signo
> 0 || signo
< SIGRTMIN
- SIGRTMAX
)
220 return signo
+ SIGRTMAX
;
226 void nop_signal_handler(int sig
) {
230 int signal_is_blocked(int sig
) {
234 r
= pthread_sigmask(SIG_SETMASK
, NULL
, &ss
);
238 return RET_NERRNO(sigismember(&ss
, sig
));
241 int pop_pending_signal_internal(int sig
, ...) {
246 if (sig
< 0) /* Empty list? */
249 if (sigemptyset(&ss
) < 0)
252 /* Add first signal (if the signal is zero, we'll silently skip it, to make it easier to build
253 * parameter lists where some element are sometimes off, similar to how sigset_add_many_ap() handles
255 if (sig
> 0 && sigaddset(&ss
, sig
) < 0)
258 /* Add all other signals */
260 r
= sigset_add_many_ap(&ss
, ap
);
265 r
= sigtimedwait(&ss
, NULL
, &(const struct timespec
) {});
273 return r
; /* Returns the signal popped */
276 void propagate_signal(int sig
, siginfo_t
*siginfo
) {
279 /* To be called from a signal handler. Will raise the same signal again, in our process + in our threads.
281 * Note that we use getpid() instead of getpid_cached(). We might have forked with raw_clone()
282 * earlier (see PID 1), and hence let's go to the raw syscall here. In particular as this is not
283 * performance sensitive code.
285 * Note that we use kill() rather than raise() as fallback, for similar reasons. */
289 if (rt_tgsigqueueinfo(p
, gettid(), sig
, siginfo
) < 0)
290 assert_se(kill(p
, sig
) >= 0);
293 const struct sigaction sigaction_ignore
= {
294 .sa_handler
= SIG_IGN
,
295 .sa_flags
= SA_RESTART
,
298 const struct sigaction sigaction_default
= {
299 .sa_handler
= SIG_DFL
,
300 .sa_flags
= SA_RESTART
,
303 const struct sigaction sigaction_nop_nocldstop
= {
304 .sa_handler
= nop_signal_handler
,
305 .sa_flags
= SA_NOCLDSTOP
|SA_RESTART
,
308 int parse_signo(const char *s
, int *ret
) {
311 r
= safe_atoi(s
, &sig
);
315 if (!SIGNAL_VALID(sig
))