Add support for sigqueue() and also handle SIGUSR2
I anticipate using sigqueue() for simpler handling of SIGCHLD notifications from the prewram process to the its parent.
This commit is contained in:
parent
ce3322bf91
commit
bf4dc6365a
@ -23,6 +23,10 @@
|
||||
#include <signal.h>
|
||||
extern PyTypeObject Screen_Type;
|
||||
|
||||
#if defined(__APPLE__) || defined(__OpenBSD__)
|
||||
#define NO_SIGQUEUE 1
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_EVENT_LOOP
|
||||
#define EVDBG(...) log_event(__VA_ARGS__)
|
||||
#else
|
||||
@ -801,11 +805,25 @@ free_twd(ThreadWriteData *x) {
|
||||
free(x);
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
sig_queue(PyObject *self UNUSED, PyObject *args) {
|
||||
int pid, signal, value;
|
||||
if (!PyArg_ParseTuple(args, "iii", &pid, &signal, &value)) return NULL;
|
||||
#ifdef NO_SIGQUEUE
|
||||
if (kill(pid, signal) != 0) { PyErr_SetFromErrno(PyExc_OSError); return NULL; }
|
||||
#else
|
||||
union sigval v;
|
||||
v.sival_int = value;
|
||||
if (sigqueue(pid, signal, v) != 0) { PyErr_SetFromErrno(PyExc_OSError); return NULL; }
|
||||
#endif
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
monitor_pid(PyObject *self UNUSED, PyObject *args) {
|
||||
long pid;
|
||||
int pid;
|
||||
bool ok = true;
|
||||
if (!PyArg_ParseTuple(args, "l", &pid)) return NULL;
|
||||
if (!PyArg_ParseTuple(args, "i", &pid)) return NULL;
|
||||
children_mutex(lock);
|
||||
if (monitored_pids_count >= arraysz(monitored_pids)) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "Too many monitored pids");
|
||||
@ -1224,7 +1242,7 @@ read_bytes(int fd, Screen *screen) {
|
||||
typedef struct { bool kill_signal, child_died, reload_config; } SignalSet;
|
||||
|
||||
static void
|
||||
handle_signal(int signum, void *data) {
|
||||
handle_signal(int32_t signum, int32_t sigval, void *data) {
|
||||
SignalSet *ss = data;
|
||||
switch(signum) {
|
||||
case SIGINT:
|
||||
@ -1237,6 +1255,9 @@ handle_signal(int signum, void *data) {
|
||||
case SIGUSR1:
|
||||
ss->reload_config = true;
|
||||
break;
|
||||
case SIGUSR2:
|
||||
printf("Received SIGUSR2: %d\n", sigval);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -1739,6 +1760,7 @@ static PyMethodDef module_methods[] = {
|
||||
METHODB(monitor_pid, METH_VARARGS),
|
||||
METHODB(send_data_to_peer, METH_VARARGS),
|
||||
METHODB(cocoa_set_menubar_title, METH_VARARGS),
|
||||
{"sigqueue", (PyCFunction)sig_queue, METH_VARARGS, ""},
|
||||
{NULL} /* Sentinel */
|
||||
};
|
||||
|
||||
@ -1748,6 +1770,11 @@ init_child_monitor(PyObject *module) {
|
||||
if (PyModule_AddObject(module, "ChildMonitor", (PyObject *)&ChildMonitor_Type) != 0) return false;
|
||||
Py_INCREF(&ChildMonitor_Type);
|
||||
if (PyModule_AddFunctions(module, module_methods) != 0) return false;
|
||||
#ifdef NO_SIGQUEUE
|
||||
PyModule_AddIntConstant(module, "has_sigqueue", 0);
|
||||
#else
|
||||
PyModule_AddIntConstant(module, "has_sigqueue", 1);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -1375,3 +1375,7 @@ def shm_open(name: str, flags: int, mode: int = 0o600) -> int:
|
||||
|
||||
def shm_unlink(name: str) -> None:
|
||||
pass
|
||||
|
||||
|
||||
def sigqueue(pid: int, signal: int, value: int) -> None:
|
||||
pass
|
||||
|
||||
@ -29,11 +29,14 @@ init_loop_data(LoopData *ld) {
|
||||
static int signal_write_fd = -1;
|
||||
|
||||
static void
|
||||
handle_signal(int sig_num) {
|
||||
handle_signal(int sig_num, siginfo_t *si, void *ucontext UNUSED) {
|
||||
int save_err = errno;
|
||||
unsigned char byte = (unsigned char)sig_num;
|
||||
while(signal_write_fd != -1) {
|
||||
ssize_t ret = write(signal_write_fd, &byte, 1);
|
||||
char buf[8];
|
||||
int32_t sigval = si->si_value.sival_int, signum = sig_num;
|
||||
memcpy(buf, &signum, 4);
|
||||
memcpy(buf + 4, &sigval, 4);
|
||||
while (signal_write_fd != -1) {
|
||||
ssize_t ret = write(signal_write_fd, buf, 8);
|
||||
if (ret < 0 && errno == EINTR) continue;
|
||||
break;
|
||||
}
|
||||
@ -45,7 +48,7 @@ handle_signal(int sig_num) {
|
||||
#define SIGNAL_SET \
|
||||
sigset_t signals = {0}; \
|
||||
sigemptyset(&signals); \
|
||||
sigaddset(&signals, SIGINT); sigaddset(&signals, SIGTERM); sigaddset(&signals, SIGCHLD); sigaddset(&signals, SIGUSR1); \
|
||||
sigaddset(&signals, SIGINT); sigaddset(&signals, SIGTERM); sigaddset(&signals, SIGCHLD); sigaddset(&signals, SIGUSR1); sigaddset(&signals, SIGUSR2); \
|
||||
|
||||
void
|
||||
free_loop_data(LoopData *ld) {
|
||||
@ -68,6 +71,8 @@ free_loop_data(LoopData *ld) {
|
||||
signal(SIGINT, SIG_DFL);
|
||||
signal(SIGTERM, SIG_DFL);
|
||||
signal(SIGCHLD, SIG_DFL);
|
||||
signal(SIGUSR1, SIG_DFL);
|
||||
signal(SIGUSR2, SIG_DFL);
|
||||
}
|
||||
#ifdef HAS_EVENT_FD
|
||||
safe_close(ld->wakeup_read_fd, __FILE__, __LINE__);
|
||||
@ -104,9 +109,9 @@ install_signal_handlers(LoopData *ld) {
|
||||
#else
|
||||
if (!self_pipe(ld->signal_fds, true)) return false;
|
||||
signal_write_fd = ld->signal_fds[1];
|
||||
struct sigaction act = {.sa_handler=handle_signal};
|
||||
struct sigaction act = {.sa_sigaction=handle_signal, .sa_flags=SA_SIGINFO};
|
||||
#define SA(which) { if (sigaction(which, &act, NULL) != 0) return false; if (siginterrupt(which, false) != 0) return false; }
|
||||
SA(SIGINT); SA(SIGTERM); SA(SIGCHLD); SA(SIGUSR1);
|
||||
SA(SIGINT); SA(SIGTERM); SA(SIGCHLD); SA(SIGUSR1); SA(SIGUSR2);
|
||||
#undef SA
|
||||
ld->signal_read_fd = ld->signal_fds[0];
|
||||
#endif
|
||||
@ -132,18 +137,25 @@ read_signals(int fd, handle_signal_func callback, void *data) {
|
||||
log_error("Incomplete signal read from signalfd");
|
||||
break;
|
||||
}
|
||||
for (size_t i = 0; i < num_signals; i++) callback(fdsi[i].ssi_signo, data);
|
||||
for (size_t i = 0; i < num_signals; i++) callback(fdsi[i].ssi_signo, fdsi[i].ssi_int, data);
|
||||
}
|
||||
#else
|
||||
static char buf[256];
|
||||
static size_t buf_pos = 0;
|
||||
while(true) {
|
||||
ssize_t len = read(fd, buf, sizeof(buf));
|
||||
ssize_t len = read(fd, buf + buf_pos, sizeof(buf) - buf_pos);
|
||||
if (len < 0) {
|
||||
if (errno == EINTR) continue;
|
||||
if (errno != EIO && errno != EAGAIN) log_error("Call to read() from read_signals() failed with error: %s", strerror(errno));
|
||||
break;
|
||||
}
|
||||
for (ssize_t i = 0; i < len; i++) callback(buf[i], data);
|
||||
buf_pos += len;
|
||||
while (buf_pos >= 8) {
|
||||
int32_t *sdata = (int32_t*)buf;
|
||||
callback(sdata[0], sdata[1], data);
|
||||
memmove(buf, buf + 8, 8);
|
||||
buf_pos -= 8;
|
||||
}
|
||||
if (len == 0) break;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -37,7 +37,7 @@ typedef struct {
|
||||
int wakeup_read_fd;
|
||||
int signal_read_fd;
|
||||
} LoopData;
|
||||
typedef void(*handle_signal_func)(int, void *data);
|
||||
typedef void(*handle_signal_func)(int32_t, int32_t, void *data);
|
||||
|
||||
bool init_loop_data(LoopData *ld);
|
||||
void free_loop_data(LoopData *ld);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user