1
0
mirror of https://github.com/systemd/systemd.git synced 2024-10-30 23:21:22 +03:00

Merge pull request #20168 from poettering/signal-util-tweak

generalize SIGINT handling in copy.c
This commit is contained in:
Yu Watanabe 2021-07-09 07:24:43 +09:00 committed by GitHub
commit 452a07cfd6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 80 additions and 18 deletions

View File

@ -253,3 +253,38 @@ int signal_is_blocked(int sig) {
return r;
}
int pop_pending_signal_internal(int sig, ...) {
sigset_t ss;
va_list ap;
int r;
if (sig < 0) /* Empty list? */
return -EINVAL;
if (sigemptyset(&ss) < 0)
return -errno;
/* Add first signal (if the signal is zero, we'll silently skip it, to make it easiert to build
* parameter lists where some element are sometimes off, similar to how sigset_add_many_ap() handles
* this.) */
if (sig > 0 && sigaddset(&ss, sig) < 0)
return -errno;
/* Add all other signals */
va_start(ap, sig);
r = sigset_add_many_ap(&ss, ap);
va_end(ap);
if (r < 0)
return r;
r = sigtimedwait(&ss, NULL, &(struct timespec) { 0, 0 });
if (r < 0) {
if (errno == EAGAIN)
return 0;
return -errno;
}
return r; /* Returns the signal popped */
}

View File

@ -62,3 +62,6 @@ static inline const char* signal_to_string_with_check(int n) {
}
int signal_is_blocked(int sig);
int pop_pending_signal_internal(int sig, ...);
#define pop_pending_signal(...) pop_pending_signal_internal(__VA_ARGS__, -1)

View File

@ -24,6 +24,7 @@
#include "nulstr-util.h"
#include "rm-rf.h"
#include "selinux-util.h"
#include "signal-util.h"
#include "stat-util.h"
#include "stdio-util.h"
#include "string-util.h"
@ -87,22 +88,6 @@ static int fd_is_nonblock_pipe(int fd) {
return FLAGS_SET(flags, O_NONBLOCK) ? FD_IS_NONBLOCKING_PIPE : FD_IS_BLOCKING_PIPE;
}
static int sigint_pending(void) {
sigset_t ss;
assert_se(sigemptyset(&ss) >= 0);
assert_se(sigaddset(&ss, SIGINT) >= 0);
if (sigtimedwait(&ss, NULL, &(struct timespec) { 0, 0 }) < 0) {
if (errno == EAGAIN)
return false;
return -errno;
}
return true;
}
int copy_bytes_full(
int fdf, int fdt,
uint64_t max_bytes,
@ -192,7 +177,7 @@ int copy_bytes_full(
return 1; /* return > 0 if we hit the max_bytes limit */
if (FLAGS_SET(copy_flags, COPY_SIGINT)) {
r = sigint_pending();
r = pop_pending_signal(SIGINT);
if (r < 0)
return r;
if (r > 0)
@ -861,7 +846,7 @@ static int fd_copy_directory(
continue;
if (FLAGS_SET(copy_flags, COPY_SIGINT)) {
r = sigint_pending();
r = pop_pending_signal(SIGINT);
if (r < 0)
return r;
if (r > 0)

View File

@ -133,11 +133,50 @@ static void test_ignore_signals(void) {
assert_se(default_signals(SIGINT, SIGUSR1, SIGUSR2, SIGTERM, SIGPIPE) >= 0);
}
static void test_pop_pending_signal(void) {
assert_se(signal_is_blocked(SIGUSR1) == 0);
assert_se(signal_is_blocked(SIGUSR2) == 0);
assert_se(pop_pending_signal(SIGUSR1) == 0);
assert_se(pop_pending_signal(SIGUSR2) == 0);
{
BLOCK_SIGNALS(SIGUSR1, SIGUSR2);
assert_se(signal_is_blocked(SIGUSR1) > 0);
assert_se(signal_is_blocked(SIGUSR2) > 0);
assert_se(pop_pending_signal(SIGUSR1) == 0);
assert_se(pop_pending_signal(SIGUSR2) == 0);
assert_se(raise(SIGUSR1) >= 0);
assert_se(pop_pending_signal(SIGUSR2) == 0);
assert_se(pop_pending_signal(SIGUSR1) == SIGUSR1);
assert_se(pop_pending_signal(SIGUSR1) == 0);
assert_se(raise(SIGUSR1) >= 0);
assert_se(raise(SIGUSR2) >= 0);
assert_cc(SIGUSR1 < SIGUSR2);
assert_se(pop_pending_signal(SIGUSR1, SIGUSR2) == SIGUSR1);
assert_se(pop_pending_signal(SIGUSR1, SIGUSR2) == SIGUSR2);
assert_se(pop_pending_signal(SIGUSR1, SIGUSR2) == 0);
}
assert_se(signal_is_blocked(SIGUSR1) == 0);
assert_se(signal_is_blocked(SIGUSR2) == 0);
assert_se(pop_pending_signal(SIGUSR1) == 0);
assert_se(pop_pending_signal(SIGUSR2) == 0);
}
int main(int argc, char *argv[]) {
test_rt_signals();
test_signal_from_string();
test_block_signals();
test_ignore_signals();
test_pop_pending_signal();
return 0;
}