From: Michael Tremer Date: Fri, 30 Jun 2023 13:32:34 +0000 (+0000) Subject: jail: Handle signals in epoll() loop X-Git-Tag: 0.9.29~104 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=47d2da8e7b954ff246f0e0c936cd3a9dee248128;p=pakfire.git jail: Handle signals in epoll() loop Signed-off-by: Michael Tremer --- diff --git a/src/libpakfire/jail.c b/src/libpakfire/jail.c index fbdf7b3c5..af7de97dc 100644 --- a/src/libpakfire/jail.c +++ b/src/libpakfire/jail.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -495,6 +496,32 @@ ERROR: return -1; } +// Signals + +static int pakfire_jail_handle_signals(struct pakfire_jail* jail) { + sigset_t mask; + int r; + + sigemptyset(&mask); + sigaddset(&mask, SIGINT); + + // Block signals + r = sigprocmask(SIG_BLOCK, &mask, NULL); + if (r < 0) { + ERROR(jail->pakfire, "Failed to block signals: %m\n"); + return r; + } + + // Create a file descriptor + r = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC); + if (r < 0) { + ERROR(jail->pakfire, "Failed to create signalfd: %m\n"); + return r; + } + + return r; +} + /* This function replaces any logging in the child process. @@ -696,6 +723,7 @@ static int pakfire_jail_wait(struct pakfire_jail* jail, struct pakfire_jail_exec int epollfd = -1; struct epoll_event ev; struct epoll_event events[EPOLL_MAX_EVENTS]; + struct signalfd_siginfo siginfo; char garbage[8]; int r = 0; @@ -713,9 +741,12 @@ static int pakfire_jail_wait(struct pakfire_jail* jail, struct pakfire_jail_exec const int log_ERROR = pakfire_jail_get_pipe_to_read(jail, &ctx->pipes.log_ERROR); const int log_DEBUG = pakfire_jail_get_pipe_to_read(jail, &ctx->pipes.log_DEBUG); + // Signals + const int signalfd = pakfire_jail_handle_signals(jail); + // Make a list of all file descriptors we are interested in - int fds[] = { - stdin, stdout, stderr, pidfd, timerfd, log_INFO, log_ERROR, log_DEBUG, + const int fds[] = { + stdin, stdout, stderr, pidfd, timerfd, signalfd, log_INFO, log_ERROR, log_DEBUG, }; // Setup epoll @@ -829,6 +860,37 @@ static int pakfire_jail_wait(struct pakfire_jail* jail, struct pakfire_jail_exec // There is nothing else to do continue; + // Handle signals + } else if (fd == signalfd) { + // Read the signal + r = read(signalfd, &siginfo, sizeof(siginfo)); + if (r < 1) { + ERROR(jail->pakfire, "Could not read signal: %m\n"); + goto ERROR; + } + + DEBUG(jail->pakfire, "Received signal %d\n", siginfo.ssi_signo); + + // Handle signals + switch (siginfo.ssi_signo) { + // Pass SIGINT down to the child process + case SIGINT: + r = pidfd_send_signal(pidfd, siginfo.ssi_signo, NULL, 0); + if (r) { + ERROR(jail->pakfire, "Could not send signal to process: %m\n"); + goto ERROR; + } + break; + + default: + ERROR(jail->pakfire, "Received unhandled signal %d\n", + siginfo.ssi_signo); + break; + } + + // Don't fall through to log processing + continue; + // Handle logging messages } else if (fd == log_INFO) { buffer = &ctx->buffers.log_INFO; @@ -909,6 +971,8 @@ ERROR: close(epollfd); if (timerfd > 0) close(timerfd); + if (signalfd > 0) + close(signalfd); return r; }