commit 93a4fe2a15738d2ecd2f97b219b3ac698bb348e4
parent d8113e4545c9ddf6cb092548df6a49306aba4ea4
Author: Joris Vink <joris@coders.se>
Date: Wed, 22 Dec 2021 09:50:26 +0100
Worker hook rework.
This commit adds improved hooks for Python and a new signal delivery hook.
For the Python API kore_worker_configure() and kore_worker_teardown() had
to be implemented before this commit. Now one can create a workerstart
and workerend method in their koreapp as those will be called when
they exist.
The new signal hook is either kore_worker_signal() or koreapp.signal.
This new hook is called after the worker event code handles the received
signal itself first.
With this commit there is also a new kore_signal_trap() API call allowing
you to more easily trap new signals. This API also also exported to the
Python part of the code under kore.sigtrap()
Diffstat:
8 files changed, 156 insertions(+), 40 deletions(-)
diff --git a/include/kore/hooks.h b/include/kore/hooks.h
@@ -22,6 +22,7 @@
#define KORE_DAEMONIZED_HOOK "kore_parent_daemonized"
void kore_seccomp_hook(void);
+void kore_worker_signal(int);
void kore_worker_teardown(void);
void kore_parent_teardown(void);
void kore_worker_configure(void);
diff --git a/include/kore/kore.h b/include/kore/kore.h
@@ -298,6 +298,7 @@ struct kore_runtime {
#endif
void (*execute)(void *);
int (*onload)(void *, int);
+ void (*signal)(void *, int);
void (*connect)(void *, struct connection *);
void (*configure)(void *, int, char **);
};
@@ -754,6 +755,7 @@ extern struct kore_server_list kore_servers;
void kore_signal(int);
void kore_shutdown(void);
+void kore_signal_trap(int);
void kore_signal_setup(void);
void kore_proctitle(const char *);
void kore_default_getopt(int, char **);
@@ -990,6 +992,7 @@ struct kore_module *kore_module_load(const char *,
void kore_runtime_execute(struct kore_runtime_call *);
int kore_runtime_onload(struct kore_runtime_call *, int);
+void kore_runtime_signal(struct kore_runtime_call *, int);
void kore_runtime_configure(struct kore_runtime_call *, int, char **);
void kore_runtime_connect(struct kore_runtime_call *, struct connection *);
#if !defined(KORE_NO_HTTP)
diff --git a/include/kore/python_api.h b/include/kore/python_api.h
@@ -51,8 +51,11 @@ extern const char *kore_pymodule;
extern struct kore_module_functions kore_python_module;
extern struct kore_runtime kore_python_runtime;
+#define KORE_PYTHON_SIGNAL_HOOK "koreapp.signal"
#define KORE_PYTHON_TEARDOWN_HOOK "koreapp.cleanup"
#define KORE_PYTHON_CONFIG_HOOK "koreapp.configure"
#define KORE_PYTHON_DAEMONIZED_HOOK "koreapp.daemonized"
+#define KORE_PYTHON_WORKER_STOP_HOOK "koreapp.workerstop"
+#define KORE_PYTHON_WORKER_START_HOOK "koreapp.workerstart"
#endif
diff --git a/include/kore/python_methods.h b/include/kore/python_methods.h
@@ -46,6 +46,7 @@ static PyObject *python_kore_worker(PyObject *, PyObject *);
static PyObject *python_kore_tracer(PyObject *, PyObject *);
static PyObject *python_kore_fatalx(PyObject *, PyObject *);
static PyObject *python_kore_task_id(PyObject *, PyObject *);
+static PyObject *python_kore_sigtrap(PyObject *, PyObject *);
static PyObject *python_kore_setname(PyObject *, PyObject *);
static PyObject *python_kore_suspend(PyObject *, PyObject *);
static PyObject *python_kore_shutdown(PyObject *, PyObject *);
@@ -98,6 +99,7 @@ static struct PyMethodDef pykore_methods[] = {
METHOD("fatal", python_kore_fatal, METH_VARARGS),
METHOD("fatalx", python_kore_fatalx, METH_VARARGS),
METHOD("task_id", python_kore_task_id, METH_NOARGS),
+ METHOD("sigtrap", python_kore_sigtrap, METH_VARARGS),
METHOD("setname", python_kore_setname, METH_VARARGS),
METHOD("suspend", python_kore_suspend, METH_VARARGS),
METHOD("shutdown", python_kore_shutdown, METH_NOARGS),
diff --git a/src/kore.c b/src/kore.c
@@ -741,6 +741,23 @@ kore_sockopt(int fd, int what, int opt)
void
kore_signal_setup(void)
{
+ kore_signal_trap(SIGHUP);
+ kore_signal_trap(SIGQUIT);
+ kore_signal_trap(SIGTERM);
+ kore_signal_trap(SIGUSR1);
+ kore_signal_trap(SIGCHLD);
+
+ if (kore_foreground)
+ kore_signal_trap(SIGINT);
+ else
+ (void)signal(SIGINT, SIG_IGN);
+
+ (void)signal(SIGPIPE, SIG_IGN);
+}
+
+void
+kore_signal_trap(int sig)
+{
struct sigaction sa;
sig_recv = 0;
@@ -750,25 +767,8 @@ kore_signal_setup(void)
if (sigfillset(&sa.sa_mask) == -1)
fatal("sigfillset: %s", errno_s);
- if (sigaction(SIGHUP, &sa, NULL) == -1)
- fatal("sigaction: %s", errno_s);
- if (sigaction(SIGQUIT, &sa, NULL) == -1)
- fatal("sigaction: %s", errno_s);
- if (sigaction(SIGTERM, &sa, NULL) == -1)
+ if (sigaction(sig, &sa, NULL) == -1)
fatal("sigaction: %s", errno_s);
- if (sigaction(SIGUSR1, &sa, NULL) == -1)
- fatal("sigaction: %s", errno_s);
- if (sigaction(SIGCHLD, &sa, NULL) == -1)
- fatal("sigaction: %s", errno_s);
-
- if (kore_foreground) {
- if (sigaction(SIGINT, &sa, NULL) == -1)
- fatal("sigaction: %s", errno_s);
- } else {
- (void)signal(SIGINT, SIG_IGN);
- }
-
- (void)signal(SIGPIPE, SIG_IGN);
}
void
@@ -961,22 +961,22 @@ kore_server_start(int argc, char *argv[])
#endif
while (kore_quit != 1) {
- if (sig_recv != 0) {
- last_sig = sig_recv;
+ last_sig = sig_recv;
- switch (sig_recv) {
+ if (last_sig != 0) {
+ switch (last_sig) {
case SIGHUP:
- kore_worker_dispatch_signal(sig_recv);
+ kore_worker_dispatch_signal(last_sig);
kore_module_reload(0);
break;
case SIGINT:
case SIGQUIT:
case SIGTERM:
kore_quit = 1;
- kore_worker_dispatch_signal(sig_recv);
+ kore_worker_dispatch_signal(last_sig);
continue;
case SIGUSR1:
- kore_worker_dispatch_signal(sig_recv);
+ kore_worker_dispatch_signal(last_sig);
break;
case SIGCHLD:
kore_worker_reap();
diff --git a/src/python.c b/src/python.c
@@ -158,6 +158,7 @@ static void python_runtime_wsmessage(void *, struct connection *,
u_int8_t, const void *, size_t);
static void python_runtime_execute(void *);
static int python_runtime_onload(void *, int);
+static void python_runtime_signal(void *, int);
static void python_runtime_configure(void *, int, char **);
static void python_runtime_connect(void *, struct connection *);
@@ -188,6 +189,7 @@ struct kore_runtime kore_python_runtime = {
.wsmessage = python_runtime_wsmessage,
.wsdisconnect = python_runtime_connect,
.onload = python_runtime_onload,
+ .signal = python_runtime_signal,
.connect = python_runtime_connect,
.execute = python_runtime_execute,
.configure = python_runtime_configure,
@@ -1643,6 +1645,22 @@ python_runtime_connect(void *addr, struct connection *c)
Py_DECREF(pyret);
}
+static void
+python_runtime_signal(void *addr, int sig)
+{
+ PyObject *obj, *ret;
+
+ if ((obj = Py_BuildValue("i", sig)) == NULL) {
+ kore_python_log_error("python_runtime_signal");
+ return;
+ }
+
+ ret = PyObject_CallFunctionObjArgs(addr, obj, NULL);
+
+ Py_DECREF(obj);
+ Py_XDECREF(ret);
+}
+
PyMODINIT_FUNC
python_module_init(void)
{
@@ -2442,6 +2460,19 @@ python_kore_setname(PyObject *self, PyObject *args)
}
static PyObject *
+python_kore_sigtrap(PyObject *self, PyObject *args)
+{
+ int sig;
+
+ if (!PyArg_ParseTuple(args, "i", &sig))
+ return (NULL);
+
+ kore_signal_trap(sig);
+
+ Py_RETURN_NONE;
+}
+
+static PyObject *
python_kore_sendobj(PyObject *self, PyObject *args, PyObject *kwargs)
{
long val;
diff --git a/src/runtime.c b/src/runtime.c
@@ -29,6 +29,7 @@
static void native_runtime_execute(void *);
static int native_runtime_onload(void *, int);
+static void native_runtime_signal(void *, int);
static void native_runtime_connect(void *, struct connection *);
static void native_runtime_configure(void *, int, char **);
#if !defined(KORE_NO_HTTP)
@@ -55,6 +56,7 @@ struct kore_runtime kore_native_runtime = {
.wsdisconnect = native_runtime_connect,
#endif
.onload = native_runtime_onload,
+ .signal = native_runtime_signal,
.connect = native_runtime_connect,
.execute = native_runtime_execute,
.configure = native_runtime_configure
@@ -102,6 +104,12 @@ kore_runtime_connect(struct kore_runtime_call *rcall, struct connection *c)
rcall->runtime->connect(rcall->addr, c);
}
+void
+kore_runtime_signal(struct kore_runtime_call *rcall, int sig)
+{
+ rcall->runtime->signal(rcall->addr, sig);
+}
+
#if !defined(KORE_NO_HTTP)
int
kore_runtime_http_request(struct kore_runtime_call *rcall,
@@ -187,6 +195,15 @@ native_runtime_onload(void *addr, int action)
return (cb(action));
}
+static void
+native_runtime_signal(void *addr, int sig)
+{
+ void (*cb)(int);
+
+ *(void **)&(cb) = addr;
+ cb(sig);
+}
+
#if !defined(KORE_NO_HTTP)
static int
native_runtime_http_request(void *addr, struct http_request *req)
diff --git a/src/worker.c b/src/worker.c
@@ -79,8 +79,12 @@ struct wlock {
static int worker_trylock(void);
static void worker_unlock(void);
static void worker_reaper(pid_t, int);
+static void worker_runtime_teardown(void);
+static void worker_runtime_configure(void);
static void worker_domain_check(struct kore_domain *);
+static struct kore_runtime_call *worker_runtime_signal(void);
+
static inline int worker_acceptlock_obtain(void);
static inline void worker_acceptlock_release(void);
static void worker_accept_avail(struct kore_msg *, const void *);
@@ -420,9 +424,9 @@ kore_worker_privsep(void)
void
kore_worker_entry(struct kore_worker *kw)
{
- struct kore_runtime_call *rcall;
+ struct kore_runtime_call *sigcall;
u_int64_t last_seed;
- int quit, had_lock;
+ int quit, had_lock, sig;
u_int64_t netwait, now, next_timeo;
worker = kw;
@@ -504,11 +508,7 @@ kore_worker_entry(struct kore_worker *kw)
if (nlisteners == 0)
worker_no_lock = 1;
- rcall = kore_runtime_getcall("kore_worker_configure");
- if (rcall != NULL) {
- kore_runtime_execute(rcall);
- kore_free(rcall);
- }
+ worker_runtime_configure();
kore_module_onload();
kore_domain_callback(worker_domain_check);
@@ -516,6 +516,8 @@ kore_worker_entry(struct kore_worker *kw)
kore_worker_started();
worker->restarted = 0;
+ sigcall = worker_runtime_signal();
+
for (;;) {
now = kore_time_ms();
@@ -564,8 +566,9 @@ kore_worker_entry(struct kore_worker *kw)
}
}
- if (sig_recv != 0) {
- switch (sig_recv) {
+ sig = sig_recv;
+ if (sig != 0) {
+ switch (sig) {
case SIGHUP:
kore_module_reload(1);
break;
@@ -583,7 +586,11 @@ kore_worker_entry(struct kore_worker *kw)
break;
}
- sig_recv = 0;
+ if (sigcall != NULL)
+ kore_runtime_signal(sigcall, sig);
+
+ if (sig == sig_recv)
+ sig_recv = 0;
}
if (quit)
@@ -608,12 +615,7 @@ kore_worker_entry(struct kore_worker *kw)
kore_connection_prune(KORE_CONNECTION_PRUNE_DISCONNECT);
}
- rcall = kore_runtime_getcall("kore_worker_teardown");
- if (rcall != NULL) {
- kore_runtime_execute(rcall);
- kore_free(rcall);
- }
-
+ worker_runtime_teardown();
kore_server_cleanup();
kore_platform_event_cleanup();
@@ -754,6 +756,63 @@ kore_worker_started(void)
}
static void
+worker_runtime_configure(void)
+{
+ struct kore_runtime_call *rcall;
+
+ rcall = NULL;
+
+#if defined(KORE_USE_PYTHON)
+ rcall = kore_runtime_getcall(KORE_PYTHON_WORKER_START_HOOK);
+#endif
+
+ if (rcall == NULL)
+ rcall = kore_runtime_getcall("kore_worker_configure");
+
+ if (rcall != NULL) {
+ kore_runtime_execute(rcall);
+ kore_free(rcall);
+ }
+}
+
+static struct kore_runtime_call *
+worker_runtime_signal(void)
+{
+ struct kore_runtime_call *rcall;
+
+ rcall = NULL;
+
+#if defined(KORE_USE_PYTHON)
+ rcall = kore_runtime_getcall(KORE_PYTHON_SIGNAL_HOOK);
+#endif
+
+ if (rcall == NULL)
+ rcall = kore_runtime_getcall("kore_worker_signal");
+
+ return (rcall);
+}
+
+static void
+worker_runtime_teardown(void)
+{
+ struct kore_runtime_call *rcall;
+
+ rcall = NULL;
+
+#if defined(KORE_USE_PYTHON)
+ rcall = kore_runtime_getcall(KORE_PYTHON_WORKER_STOP_HOOK);
+#endif
+
+ if (rcall == NULL)
+ rcall = kore_runtime_getcall("kore_worker_teardown");
+
+ if (rcall != NULL) {
+ kore_runtime_execute(rcall);
+ kore_free(rcall);
+ }
+}
+
+static void
worker_domain_check(struct kore_domain *dom)
{
struct stat st;