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()
This commit is contained in:
Joris Vink 2021-12-22 09:50:26 +01:00
parent d8113e4545
commit 93a4fe2a15
8 changed files with 156 additions and 40 deletions

View File

@ -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);

View File

@ -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)

View File

@ -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

View File

@ -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),

View File

@ -740,6 +740,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;
@ -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)
if (sigaction(sig, &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)
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();

View File

@ -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)
{
@ -2441,6 +2459,19 @@ python_kore_setname(PyObject *self, PyObject *args)
Py_RETURN_NONE;
}
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)
{

View File

@ -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)

View File

@ -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();
@ -753,6 +755,63 @@ kore_worker_started(void)
worker->ready = 1;
}
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)
{