Commit 7dddb6c0 authored by Marek Vavrusa's avatar Marek Vavrusa

Merge branch 'control-socket-activation' into 'master'

Control socket activation

This branch provides reasonable configs for full systemd socket activation for kresd.

See merge request !36
parents 6887a4a2 023b92a4
......@@ -23,7 +23,6 @@
......@@ -321,7 +321,7 @@ static struct worker_ctx *init_worker(struct engine *engine, knot_mm_t *pool, in
return worker;
static int run_worker(uv_loop_t *loop, struct engine *engine, fd_array_t *ipc_set, bool leader)
static int run_worker(uv_loop_t *loop, struct engine *engine, fd_array_t *ipc_set, bool leader, int control_fd)
/* Control sockets or TTY */
auto_free char *sock_file = NULL;
......@@ -335,12 +335,18 @@ static int run_worker(uv_loop_t *loop, struct engine *engine, fd_array_t *ipc_se
uv_pipe_open(&pipe, 0);
uv_read_start((uv_stream_t*) &pipe, tty_alloc, tty_read);
} else {
(void) mkdir("tty", S_IRWXU|S_IRWXG);
sock_file = afmt("tty/%ld", getpid());
if (sock_file) {
uv_pipe_bind(&pipe, sock_file);
uv_listen((uv_stream_t *) &pipe, 16, tty_accept);
int pipe_ret = -1;
if (control_fd != -1) {
pipe_ret = uv_pipe_open(&pipe, control_fd);
} else {
(void) mkdir("tty", S_IRWXU|S_IRWXG);
sock_file = afmt("tty/%ld", getpid());
if (sock_file) {
pipe_ret = uv_pipe_bind(&pipe, sock_file);
if (!pipe_ret)
uv_listen((uv_stream_t *) &pipe, 16, tty_accept);
/* Watch IPC pipes (or just assign them if leading the pgroup). */
if (!leader) {
......@@ -364,6 +370,14 @@ static int run_worker(uv_loop_t *loop, struct engine *engine, fd_array_t *ipc_se
return kr_ok();
void free_sd_socket_names(char **socket_names, int count)
for (int i = 0; i < count; i++) {
int main(int argc, char **argv)
int forks = 1;
......@@ -374,6 +388,7 @@ int main(int argc, char **argv)
char *keyfile = NULL;
const char *config = NULL;
char *keyfile_buf = NULL;
int control_fd = -1;
/* Long options. */
int c = 0, li = 0, ret = 0;
......@@ -457,11 +472,25 @@ int main(int argc, char **argv)
/* Accept passed sockets from systemd supervisor. */
int sd_nsocks = sd_listen_fds(0);
char **socket_names = NULL;
int sd_nsocks = sd_listen_fds_with_names(0, &socket_names);
for (int i = 0; i < sd_nsocks; ++i) {
int fd = SD_LISTEN_FDS_START + i;
array_push(fd_set, fd);
/* when run under systemd supervision, do not use interactive mode */
g_interactive = false;
if (forks != 1) {
kr_log_error("[system] when run under systemd-style supervision, "
"use single-process only (bad: --fork=%d).\n", forks);
free_sd_socket_names(socket_names, sd_nsocks);
if (!strcasecmp("control",socket_names[i])) {
control_fd = fd;
} else {
array_push(fd_set, fd);
free_sd_socket_names(socket_names, sd_nsocks);
/* Switch to rundir. */
......@@ -563,7 +592,7 @@ int main(int argc, char **argv)
lua_settop(engine.L, 0);
/* Run the event loop */
ret = run_worker(loop, &engine, &ipc_set, fork_id == 0);
ret = run_worker(loop, &engine, &ipc_set, fork_id == 0, control_fd);
if (ret != 0) {
......@@ -111,6 +111,10 @@ With this option, the daemon is started in non-interactive mode and instead crea
UNIX socket in \fIrundir\fR that the operator can connect to for interactive session.
A number greater than 1 forks the daemon N times, all forks will bind to same addresses
and the kernel will load-balance between them on Linux with \fISO_REUSEPORT\fR support.
When socket-activated and supervised by systemd or the equivalent, kresd defaults to
--forks=1, and must not be set to any other value. If you want multiple concurrent
processes supervised in this way, they should be supervised independently.
.B \-q\fR, \fB\-\-quiet
Daemon will refrain from printing any informative messages, not even a prompt.
Description=Knot DNS Resolver daemon
ExecStart=/usr/sbin/kresd -c /etc/kresd/config -f $KRESD_WORKERS $KRESD_OPTIONS /var/lib/kresd/
## Path: System/DNS
## Description: Number of worker processes to spawn
## Type: integer
## Default: 1
## ServiceRestart: kresd
# Number of workers to spawn for kresd.
# If you get start up failures with "already in use" your libuv is too
# old and you have to stick to 1.
# Additional options
Running Knot Resolver under systemd (or equivalent) socket activation
You can use the files in this directory to run kresd under supervision
by systemd (or any supervisor that provides equivalent file descriptor
initialization via the interface supported by
When run in this configuration:
* it will be run under a non-privileged user, which means it will not
be able to open any new non-privileged ports.
* it will use a single process (implicitly uses --forks=1, and will
fail if that configuration variable is set to a different value).
If you want multiple daemons to listen on these ports publicly
concurrently, you'll need the supervisor to manage them
differently, for example via a systemd generator:
If you have a useful systemd generator for multiple concurrent
processes, please contribute it upstream!
Description=Knot DNS Resolver control socket
Description=Knot DNS Resolver daemon
## This is a socket-activated service:
Description=Knot DNS Resolver network listeners
# tmpfiles.d(5) runtime directory for knot-resolver (kresd)
#Type Path Mode UID GID Age Argument
d /run/knot-resolver 0750 root root - -
d /run/knot-resolver/cache 0750 knot-resolver knot-resolver - -
L /run/knot-resolver/cache/config 0750 knot-resolver knot-resolver - /etc/knot-resolver/kresd.conf
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment