]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/basic/signal-util.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
6 #include "errno-util.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) {
15 static const struct sigaction sa
= {
16 .sa_handler
= SIG_DFL
,
17 .sa_flags
= SA_RESTART
,
21 for (int sig
= 1; sig
< _NSIG
; sig
++) {
23 /* These two cannot be caught... */
24 if (IN_SET(sig
, SIGKILL
, SIGSTOP
))
27 /* On Linux the first two RT signals are reserved by
28 * glibc, and sigaction() will return EINVAL for them. */
29 if (sigaction(sig
, &sa
, NULL
) < 0)
30 if (errno
!= EINVAL
&& r
>= 0)
37 int reset_signal_mask(void) {
40 if (sigemptyset(&ss
) < 0)
43 return RET_NERRNO(sigprocmask(SIG_SETMASK
, &ss
, NULL
));
46 int sigaction_many_internal(const struct sigaction
*sa
, ...) {
52 /* negative signal ends the list. 0 signal is skipped. */
53 while ((sig
= va_arg(ap
, int)) >= 0) {
58 if (sigaction(sig
, sa
, NULL
) < 0) {
69 static int sigset_add_many_ap(sigset_t
*ss
, va_list ap
) {
74 while ((sig
= va_arg(ap
, int)) >= 0) {
79 if (sigaddset(ss
, sig
) < 0) {
88 int sigset_add_many(sigset_t
*ss
, ...) {
93 r
= sigset_add_many_ap(ss
, ap
);
99 int sigprocmask_many(int how
, sigset_t
*old
, ...) {
104 if (sigemptyset(&ss
) < 0)
108 r
= sigset_add_many_ap(&ss
, ap
);
114 if (sigprocmask(how
, &ss
, old
) < 0)
120 static const char *const static_signal_table
[] = {
137 [SIGSTKFLT
] = "STKFLT", /* Linux on SPARC doesn't know SIGSTKFLT */
148 [SIGVTALRM
] = "VTALRM",
150 [SIGWINCH
] = "WINCH",
156 DEFINE_PRIVATE_STRING_TABLE_LOOKUP(static_signal
, int);
158 const char *signal_to_string(int signo
) {
159 static thread_local
char buf
[STRLEN("RTMIN+") + DECIMAL_STR_MAX(int)];
162 name
= static_signal_to_string(signo
);
166 if (signo
>= SIGRTMIN
&& signo
<= SIGRTMAX
)
167 xsprintf(buf
, "RTMIN+%d", signo
- SIGRTMIN
);
169 xsprintf(buf
, "%d", signo
);
174 int signal_from_string(const char *s
) {
178 /* Check that the input is a signal number. */
179 if (safe_atoi(s
, &signo
) >= 0) {
180 if (SIGNAL_VALID(signo
))
186 /* Drop "SIG" prefix. */
187 if (startswith(s
, "SIG"))
190 /* Check that the input is a signal name. */
191 signo
= static_signal_from_string(s
);
195 /* Check that the input is RTMIN or
196 * RTMIN+n (0 <= n <= SIGRTMAX-SIGRTMIN). */
197 p
= startswith(s
, "RTMIN");
204 r
= safe_atoi(p
, &signo
);
208 if (signo
< 0 || signo
> SIGRTMAX
- SIGRTMIN
)
211 return signo
+ SIGRTMIN
;
214 /* Check that the input is RTMAX or
215 * RTMAX-n (0 <= n <= SIGRTMAX-SIGRTMIN). */
216 p
= startswith(s
, "RTMAX");
223 r
= safe_atoi(p
, &signo
);
227 if (signo
> 0 || signo
< SIGRTMIN
- SIGRTMAX
)
230 return signo
+ SIGRTMAX
;
236 void nop_signal_handler(int sig
) {
240 int signal_is_blocked(int sig
) {
244 r
= pthread_sigmask(SIG_SETMASK
, NULL
, &ss
);
248 return RET_NERRNO(sigismember(&ss
, sig
));
251 int pop_pending_signal_internal(int sig
, ...) {
256 if (sig
< 0) /* Empty list? */
259 if (sigemptyset(&ss
) < 0)
262 /* Add first signal (if the signal is zero, we'll silently skip it, to make it easier to build
263 * parameter lists where some element are sometimes off, similar to how sigset_add_many_ap() handles
265 if (sig
> 0 && sigaddset(&ss
, sig
) < 0)
268 /* Add all other signals */
270 r
= sigset_add_many_ap(&ss
, ap
);
275 r
= sigtimedwait(&ss
, NULL
, &(struct timespec
) { 0, 0 });
283 return r
; /* Returns the signal popped */