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 c7dccaa8e37c5adf45656a93653f4ee7423fb61d
parent 16fd3092d7565eb90f4487e7314d780cec99a67f
Author: Joris Vink <joris@sanctorum.se>
Date:   Fri, 23 Jan 2026 22:51:49 +0100

Add worker_no_accept.

This allows you to turn off accepting normal connections on workers
which in turn makes you able to dedicate them to other things.

Like sending python objects from worker A to worker B so B can do the
heavy lifting of things while A keeps on processing HTTP requests.

Diffstat:
conf/kore.conf.example | 3+++
include/kore/kore.h | 6++++--
src/config.c | 19+++++++++++++++++++
src/worker.c | 49+++++++++++++++++++++++++++++++++++++++++--------
4 files changed, 67 insertions(+), 10 deletions(-)

diff --git a/conf/kore.conf.example b/conf/kore.conf.example @@ -93,6 +93,9 @@ workers 4 # You might have to tweak this number based on your hardware. #worker_max_connections 512 +# Disable accepting of normal connections on a given worker process. +#worker_no_accept 2 + # Limit of maximum open files per worker. #worker_rlimit_nofiles 768 diff --git a/include/kore/kore.h b/include/kore/kore.h @@ -472,7 +472,8 @@ struct kore_worker { pid_t pid; int pipe[2]; struct connection *msg[2]; - u_int8_t has_lock; + int has_lock; + int no_accept; int restarted; u_int64_t time_locked; struct kore_route *active_route; @@ -774,8 +775,9 @@ void kore_worker_reap(void); int kore_worker_init(void); void kore_worker_privsep(void); void kore_worker_started(void); -void kore_worker_make_busy(void); void kore_worker_shutdown(void); +void kore_worker_make_busy(void); +void kore_worker_no_accept(u_int8_t); void kore_worker_dispatch_signal(int); int kore_worker_spawn(u_int16_t, u_int16_t, u_int16_t); int kore_worker_keymgr_response_verify(struct kore_msg *, diff --git a/src/config.c b/src/config.c @@ -84,6 +84,7 @@ static int configure_privsep(char *); static int configure_logfile(char *); static int configure_workers(char *); static int configure_pidfile(char *); +static int configure_no_accept(char *); static int configure_rlimit_nofiles(char *); static int configure_max_connections(char *); static int configure_accept_threshold(char *); @@ -235,6 +236,7 @@ static struct { { "worker_death_policy", configure_death_policy }, { "worker_set_affinity", configure_set_affinity }, { "pidfile", configure_pidfile }, + { "worker_no_accept", configure_no_accept }, { "socket_backlog", configure_socket_backlog }, { "tls_version", configure_tls_version }, { "tls_cipher", configure_tls_cipher }, @@ -1877,6 +1879,23 @@ configure_pidfile(char *path) } static int +configure_no_accept(char *option) +{ + int err, idx; + + idx = kore_strtonum(option, 10, 1, KORE_WORKER_MAX, &err); + if (err != KORE_RESULT_OK) { + kore_log(LOG_ERR, + "bad value for worker_no_accept '%s'", option); + return (KORE_RESULT_ERROR); + } + + kore_worker_no_accept(idx); + + return (KORE_RESULT_OK); +} + +static int configure_max_connections(char *option) { int err; diff --git a/src/worker.c b/src/worker.c @@ -99,6 +99,7 @@ u_int32_t worker_accept_threshold = 16; u_int32_t worker_rlimit_nofiles = 768; u_int32_t worker_max_connections = 512; u_int32_t worker_active_connections = 0; +u_int8_t worker_no_accept[KORE_WORKER_MAX]; int worker_policy = KORE_WORKER_POLICY_RESTART; int @@ -188,6 +189,9 @@ kore_worker_spawn(u_int16_t idx, u_int16_t id, u_int16_t cpu) int status; #endif + if (idx >= KORE_WORKER_MAX) + fatal("%u > KORE_WORKER_MAX", idx); + kw = WORKER(idx); kw->id = id; kw->cpu = cpu; @@ -196,6 +200,7 @@ kore_worker_spawn(u_int16_t idx, u_int16_t id, u_int16_t cpu) kw->ready = 0; kw->has_lock = 0; kw->active_route = NULL; + kw->no_accept = worker_no_accept[id]; if (socketpair(AF_UNIX, SOCK_STREAM, 0, kw->pipe) == -1) fatal("socketpair(): %s", errno_s); @@ -440,6 +445,12 @@ kore_worker_privsep(void) } void +kore_worker_no_accept(u_int8_t idx) +{ + worker_no_accept[idx] = 1; +} + +void kore_worker_entry(struct kore_worker *kw) { struct kore_runtime_call *sigcall; @@ -543,7 +554,8 @@ kore_worker_entry(struct kore_worker *kw) last_seed = now; } - if (!worker->has_lock && accept_avail) { + if (worker->no_accept == 0 && + !worker->has_lock && accept_avail) { if (worker_acceptlock_obtain()) { accept_avail = 0; if (had_lock == 0) { @@ -572,13 +584,15 @@ kore_worker_entry(struct kore_worker *kw) kore_platform_event_wait(netwait); now = kore_time_ms(); - if (worker->has_lock) - worker_acceptlock_release(); + if (worker->no_accept == 0) { + if (worker->has_lock) + worker_acceptlock_release(); - if (!worker->has_lock) { - if (had_lock == 1) { - had_lock = 0; - kore_platform_disable_accept(); + if (!worker->has_lock) { + if (had_lock == 1) { + had_lock = 0; + kore_platform_disable_accept(); + } } } @@ -618,7 +632,8 @@ kore_worker_entry(struct kore_worker *kw) kore_curl_do_timeout(); #endif #if !defined(KORE_NO_HTTP) - http_process(); + if (worker->no_accept == 0) + http_process(); #endif #if defined(KORE_USE_PYTHON) kore_python_coro_run(); @@ -683,6 +698,9 @@ kore_worker_reap(void) void kore_worker_make_busy(void) { + if (worker->no_accept) + fatal("%s called with no_accept set", __func__); + if (worker_count == WORKER_SOLO_COUNT || worker_no_lock == 1) return; @@ -943,6 +961,9 @@ worker_reaper(pid_t pid, int status) static inline void worker_acceptlock_release(void) { + if (worker->no_accept) + fatal("%s called with no_accept set", __func__); + if (worker_count == WORKER_SOLO_COUNT || worker_no_lock == 1) return; @@ -973,6 +994,9 @@ worker_acceptlock_obtain(void) { int r; + if (worker->no_accept) + fatal("%s called with no_accept set", __func__); + if (worker->has_lock == 1) return (1); @@ -1004,6 +1028,9 @@ worker_acceptlock_obtain(void) static int worker_trylock(void) { + if (worker->no_accept) + fatal("%s called with no_accept set", __func__); + if (!__sync_bool_compare_and_swap(&(accept_lock->lock), 0, 1)) return (0); @@ -1015,6 +1042,9 @@ worker_trylock(void) static void worker_unlock(void) { + if (worker->no_accept) + fatal("%s called with no_accept set", __func__); + accept_lock->current = 0; if (!__sync_bool_compare_and_swap(&(accept_lock->lock), 1, 0)) kore_log(LOG_NOTICE, "worker_unlock(): wasn't locked"); @@ -1023,6 +1053,9 @@ worker_unlock(void) static void worker_accept_avail(struct kore_msg *msg, const void *data) { + if (worker->no_accept) + fatal("%s called with no_accept set", __func__); + accept_avail = 1; }