kore

Kore is a web application platform for writing scalable, concurrent web based processes in C or Python.
Commits | Files | Refs | README | LICENSE | git clone https://git.kore.io/kore.git

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:
include/kore/hooks.h | 1+
include/kore/kore.h | 3+++
include/kore/python_api.h | 3+++
include/kore/python_methods.h | 2++
src/kore.c | 48++++++++++++++++++++++++------------------------
src/python.c | 31+++++++++++++++++++++++++++++++
src/runtime.c | 17+++++++++++++++++
src/worker.c | 91+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------
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;