Skip to content
Snippets Groups Projects
Commit 7dddb6c0 authored by Marek Vavrusa's avatar Marek Vavrusa
Browse files

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
No related tags found
No related merge requests found
......@@ -23,7 +23,6 @@
.libs
.deps
_obj
tmp*
/autom4te.cache/*
/config.log
/config.h
......
......@@ -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++) {
free(socket_names[i]);
}
free(socket_names);
}
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)
#ifdef HAS_SYSTEMD
/* 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);
return EXIT_FAILURE;
}
if (!strcasecmp("control",socket_names[i])) {
control_fd = fd;
} else {
array_push(fd_set, fd);
}
}
free_sd_socket_names(socket_names, sd_nsocks);
#endif
/* 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.
.TP
.B \-q\fR, \fB\-\-quiet
Daemon will refrain from printing any informative messages, not even a prompt.
......
[Unit]
Description=Knot DNS Resolver daemon
After=network.target
[Service]
Type=simple
EnvironmentFile=-/etc/sysconfig/kresd
ExecStart=/usr/sbin/kresd -c /etc/kresd/config -f $KRESD_WORKERS $KRESD_OPTIONS /var/lib/kresd/
Restart=on-abort
[Install]
WantedBy=multi-user.target
## 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.
#
KRESD_WORKERS=1
# Additional options
KRESD_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
sd_listen_fds_with_names(3)).
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:
https://www.freedesktop.org/software/systemd/man/systemd.generator.html
If you have a useful systemd generator for multiple concurrent
processes, please contribute it upstream!
[Unit]
Description=Knot DNS Resolver control socket
Documentation=man:kresd(8)
Before=sockets.target
[Socket]
ListenStream=/run/knot-resolver/control
FileDescriptorName=control
Service=knot-resolver.service
SocketMode=0660
[Install]
WantedBy=sockets.target
[Unit]
Description=Knot DNS Resolver daemon
## This is a socket-activated service:
RefuseManualStart=true
[Service]
Type=notify
WorkingDirectory=/run/knot-resolver/cache
ExecStart=/usr/sbin/kresd
User=knot-resolver
Restart=on-failure
[Install]
WantedBy=sockets.target
[Unit]
Description=Knot DNS Resolver network listeners
Documentation=man:kresd(8)
Before=sockets.target
[Socket]
ListenStream=[::1]:53
ListenDatagram=[::1]:53
ListenStream=127.0.0.1:53
ListenDatagram=127.0.0.1:53
[Install]
WantedBy=sockets.target
# 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
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment