Make the full signal info available in our signal handler

This commit is contained in:
Kovid Goyal
2022-06-05 07:22:38 +05:30
parent a42200a430
commit f29039db29
3 changed files with 36 additions and 23 deletions

View File

@@ -1242,9 +1242,9 @@ read_bytes(int fd, Screen *screen) {
typedef struct { bool kill_signal, child_died, reload_config; } SignalSet; typedef struct { bool kill_signal, child_died, reload_config; } SignalSet;
static void static void
handle_signal(int32_t signum, int32_t sigval, void *data) { handle_signal(const siginfo_t *siginfo, void *data) {
SignalSet *ss = data; SignalSet *ss = data;
switch(signum) { switch(siginfo->si_signo) {
case SIGINT: case SIGINT:
case SIGTERM: case SIGTERM:
ss->kill_signal = true; ss->kill_signal = true;
@@ -1256,7 +1256,7 @@ handle_signal(int32_t signum, int32_t sigval, void *data) {
ss->reload_config = true; ss->reload_config = true;
break; break;
case SIGUSR2: case SIGUSR2:
log_error("Received SIGUSR2: %d\n", sigval); log_error("Received SIGUSR2: %d\n", siginfo->si_value.sival_int);
break; break;
default: default:
break; break;

View File

@@ -7,7 +7,6 @@
#include "loop-utils.h" #include "loop-utils.h"
#include "safe-wrappers.h" #include "safe-wrappers.h"
#include <signal.h>
bool bool
init_loop_data(LoopData *ld) { init_loop_data(LoopData *ld) {
@@ -29,16 +28,20 @@ init_loop_data(LoopData *ld) {
static int signal_write_fd = -1; static int signal_write_fd = -1;
static void static void
handle_signal(int sig_num, siginfo_t *si, void *ucontext UNUSED) { handle_signal(int sig_num UNUSED, siginfo_t *si, void *ucontext UNUSED) {
int save_err = errno; int save_err = errno;
char buf[8]; char *buf = (char*)si;
int32_t sigval = si->si_value.sival_int, signum = sig_num; size_t sz = sizeof(siginfo_t);
memcpy(buf, &signum, 4); while (signal_write_fd != -1 && sz) {
memcpy(buf + 4, &sigval, 4); // as long as sz is less than PIPE_BUF write will either write all or return -1 with EAGAIN
while (signal_write_fd != -1) { // so we are guaranteed atomic writes
ssize_t ret = write(signal_write_fd, buf, 8); ssize_t ret = write(signal_write_fd, buf, sz);
if (ret < 0 && errno == EINTR) continue; if (ret <= 0) {
break; if (errno == EINTR) continue;
break;
}
sz -= ret;
buf += ret;
} }
errno = save_err; errno = save_err;
} }
@@ -109,8 +112,8 @@ install_signal_handlers(LoopData *ld) {
#else #else
if (!self_pipe(ld->signal_fds, true)) return false; if (!self_pipe(ld->signal_fds, true)) return false;
signal_write_fd = ld->signal_fds[1]; signal_write_fd = ld->signal_fds[1];
struct sigaction act = {.sa_sigaction=handle_signal, .sa_flags=SA_SIGINFO}; struct sigaction act = {.sa_sigaction=handle_signal, .sa_flags=SA_SIGINFO | SA_RESTART};
#define SA(which) { if (sigaction(which, &act, NULL) != 0) return false; if (siginterrupt(which, false) != 0) return false; } #define SA(which) { if (sigaction(which, &act, NULL) != 0) return false; }
SA(SIGINT); SA(SIGTERM); SA(SIGCHLD); SA(SIGUSR1); SA(SIGUSR2); SA(SIGINT); SA(SIGTERM); SA(SIGCHLD); SA(SIGUSR1); SA(SIGUSR2);
#undef SA #undef SA
ld->signal_read_fd = ld->signal_fds[0]; ld->signal_read_fd = ld->signal_fds[0];
@@ -123,6 +126,7 @@ void
read_signals(int fd, handle_signal_func callback, void *data) { read_signals(int fd, handle_signal_func callback, void *data) {
#ifdef HAS_SIGNAL_FD #ifdef HAS_SIGNAL_FD
static struct signalfd_siginfo fdsi[32]; static struct signalfd_siginfo fdsi[32];
siginfo_t si;
while (true) { while (true) {
ssize_t s = read(fd, &fdsi, sizeof(fdsi)); ssize_t s = read(fd, &fdsi, sizeof(fdsi));
if (s < 0) { if (s < 0) {
@@ -137,10 +141,19 @@ read_signals(int fd, handle_signal_func callback, void *data) {
log_error("Incomplete signal read from signalfd"); log_error("Incomplete signal read from signalfd");
break; break;
} }
for (size_t i = 0; i < num_signals; i++) callback(fdsi[i].ssi_signo, fdsi[i].ssi_int, data); for (size_t i = 0; i < num_signals; i++) {
si.si_signo = fdsi[i].ssi_signo;
si.si_code = fdsi[i].ssi_code;
si.si_pid = fdsi[i].ssi_pid;
si.si_uid = fdsi[i].ssi_uid;
si.si_addr = (void*)fdsi[i].ssi_addr;
si.si_status = fdsi[i].ssi_status;
si.si_value.sival_int = fdsi[i].ssi_int;
callback(&si, data);
}
} }
#else #else
static char buf[256]; static char buf[sizeof(siginfo_t) * 8];
static size_t buf_pos = 0; static size_t buf_pos = 0;
while(true) { while(true) {
ssize_t len = read(fd, buf + buf_pos, sizeof(buf) - buf_pos); ssize_t len = read(fd, buf + buf_pos, sizeof(buf) - buf_pos);
@@ -150,11 +163,10 @@ read_signals(int fd, handle_signal_func callback, void *data) {
break; break;
} }
buf_pos += len; buf_pos += len;
while (buf_pos >= 8) { while (buf_pos >= sizeof(siginfo_t)) {
int32_t *sdata = (int32_t*)buf; callback((siginfo_t*)buf, data);
callback(sdata[0], sdata[1], data); memmove(buf, buf + sizeof(siginfo_t), sizeof(siginfo_t));
memmove(buf, buf + 8, 8); buf_pos -= sizeof(siginfo_t);
buf_pos -= 8;
} }
if (len == 0) break; if (len == 0) break;
} }

View File

@@ -9,6 +9,7 @@
#include "data-types.h" #include "data-types.h"
#include <fcntl.h> #include <fcntl.h>
#include <unistd.h> #include <unistd.h>
#include <signal.h>
#ifdef __has_include #ifdef __has_include
#if __has_include(<sys/signalfd.h>) #if __has_include(<sys/signalfd.h>)
@@ -37,7 +38,7 @@ typedef struct {
int wakeup_read_fd; int wakeup_read_fd;
int signal_read_fd; int signal_read_fd;
} LoopData; } LoopData;
typedef void(*handle_signal_func)(int32_t, int32_t, void *data); typedef void(*handle_signal_func)(const siginfo_t* siginfo, void *data);
bool init_loop_data(LoopData *ld); bool init_loop_data(LoopData *ld);
void free_loop_data(LoopData *ld); void free_loop_data(LoopData *ld);