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>
|
#include <signal.h>
|
||||||
extern PyTypeObject Screen_Type;
|
extern PyTypeObject Screen_Type;
|
||||||
|
|
||||||
|
#if defined(__APPLE__) || defined(__OpenBSD__)
|
||||||
|
#define NO_SIGQUEUE 1
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef DEBUG_EVENT_LOOP
|
#ifdef DEBUG_EVENT_LOOP
|
||||||
#define EVDBG(...) log_event(__VA_ARGS__)
|
#define EVDBG(...) log_event(__VA_ARGS__)
|
||||||
#else
|
#else
|
||||||
@ -801,11 +805,25 @@ free_twd(ThreadWriteData *x) {
|
|||||||
free(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*
|
static PyObject*
|
||||||
monitor_pid(PyObject *self UNUSED, PyObject *args) {
|
monitor_pid(PyObject *self UNUSED, PyObject *args) {
|
||||||
long pid;
|
int pid;
|
||||||
bool ok = true;
|
bool ok = true;
|
||||||
if (!PyArg_ParseTuple(args, "l", &pid)) return NULL;
|
if (!PyArg_ParseTuple(args, "i", &pid)) return NULL;
|
||||||
children_mutex(lock);
|
children_mutex(lock);
|
||||||
if (monitored_pids_count >= arraysz(monitored_pids)) {
|
if (monitored_pids_count >= arraysz(monitored_pids)) {
|
||||||
PyErr_SetString(PyExc_RuntimeError, "Too many 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;
|
typedef struct { bool kill_signal, child_died, reload_config; } SignalSet;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
handle_signal(int signum, void *data) {
|
handle_signal(int32_t signum, int32_t sigval, void *data) {
|
||||||
SignalSet *ss = data;
|
SignalSet *ss = data;
|
||||||
switch(signum) {
|
switch(signum) {
|
||||||
case SIGINT:
|
case SIGINT:
|
||||||
@ -1237,6 +1255,9 @@ handle_signal(int signum, void *data) {
|
|||||||
case SIGUSR1:
|
case SIGUSR1:
|
||||||
ss->reload_config = true;
|
ss->reload_config = true;
|
||||||
break;
|
break;
|
||||||
|
case SIGUSR2:
|
||||||
|
printf("Received SIGUSR2: %d\n", sigval);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1739,6 +1760,7 @@ static PyMethodDef module_methods[] = {
|
|||||||
METHODB(monitor_pid, METH_VARARGS),
|
METHODB(monitor_pid, METH_VARARGS),
|
||||||
METHODB(send_data_to_peer, METH_VARARGS),
|
METHODB(send_data_to_peer, METH_VARARGS),
|
||||||
METHODB(cocoa_set_menubar_title, METH_VARARGS),
|
METHODB(cocoa_set_menubar_title, METH_VARARGS),
|
||||||
|
{"sigqueue", (PyCFunction)sig_queue, METH_VARARGS, ""},
|
||||||
{NULL} /* Sentinel */
|
{NULL} /* Sentinel */
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1748,6 +1770,11 @@ init_child_monitor(PyObject *module) {
|
|||||||
if (PyModule_AddObject(module, "ChildMonitor", (PyObject *)&ChildMonitor_Type) != 0) return false;
|
if (PyModule_AddObject(module, "ChildMonitor", (PyObject *)&ChildMonitor_Type) != 0) return false;
|
||||||
Py_INCREF(&ChildMonitor_Type);
|
Py_INCREF(&ChildMonitor_Type);
|
||||||
if (PyModule_AddFunctions(module, module_methods) != 0) return false;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1375,3 +1375,7 @@ def shm_open(name: str, flags: int, mode: int = 0o600) -> int:
|
|||||||
|
|
||||||
def shm_unlink(name: str) -> None:
|
def shm_unlink(name: str) -> None:
|
||||||
pass
|
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 int signal_write_fd = -1;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
handle_signal(int sig_num) {
|
handle_signal(int sig_num, siginfo_t *si, void *ucontext UNUSED) {
|
||||||
int save_err = errno;
|
int save_err = errno;
|
||||||
unsigned char byte = (unsigned char)sig_num;
|
char buf[8];
|
||||||
while(signal_write_fd != -1) {
|
int32_t sigval = si->si_value.sival_int, signum = sig_num;
|
||||||
ssize_t ret = write(signal_write_fd, &byte, 1);
|
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;
|
if (ret < 0 && errno == EINTR) continue;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -45,7 +48,7 @@ handle_signal(int sig_num) {
|
|||||||
#define SIGNAL_SET \
|
#define SIGNAL_SET \
|
||||||
sigset_t signals = {0}; \
|
sigset_t signals = {0}; \
|
||||||
sigemptyset(&signals); \
|
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
|
void
|
||||||
free_loop_data(LoopData *ld) {
|
free_loop_data(LoopData *ld) {
|
||||||
@ -68,6 +71,8 @@ free_loop_data(LoopData *ld) {
|
|||||||
signal(SIGINT, SIG_DFL);
|
signal(SIGINT, SIG_DFL);
|
||||||
signal(SIGTERM, SIG_DFL);
|
signal(SIGTERM, SIG_DFL);
|
||||||
signal(SIGCHLD, SIG_DFL);
|
signal(SIGCHLD, SIG_DFL);
|
||||||
|
signal(SIGUSR1, SIG_DFL);
|
||||||
|
signal(SIGUSR2, SIG_DFL);
|
||||||
}
|
}
|
||||||
#ifdef HAS_EVENT_FD
|
#ifdef HAS_EVENT_FD
|
||||||
safe_close(ld->wakeup_read_fd, __FILE__, __LINE__);
|
safe_close(ld->wakeup_read_fd, __FILE__, __LINE__);
|
||||||
@ -104,9 +109,9 @@ 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_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; }
|
#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
|
#undef SA
|
||||||
ld->signal_read_fd = ld->signal_fds[0];
|
ld->signal_read_fd = ld->signal_fds[0];
|
||||||
#endif
|
#endif
|
||||||
@ -132,18 +137,25 @@ 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, data);
|
for (size_t i = 0; i < num_signals; i++) callback(fdsi[i].ssi_signo, fdsi[i].ssi_int, data);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
static char buf[256];
|
static char buf[256];
|
||||||
|
static size_t buf_pos = 0;
|
||||||
while(true) {
|
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 (len < 0) {
|
||||||
if (errno == EINTR) continue;
|
if (errno == EINTR) continue;
|
||||||
if (errno != EIO && errno != EAGAIN) log_error("Call to read() from read_signals() failed with error: %s", strerror(errno));
|
if (errno != EIO && errno != EAGAIN) log_error("Call to read() from read_signals() failed with error: %s", strerror(errno));
|
||||||
break;
|
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;
|
if (len == 0) break;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -37,7 +37,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)(int, void *data);
|
typedef void(*handle_signal_func)(int32_t, int32_t, 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);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user