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 @@
.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;
......@@ -334,14 +334,20 @@ static int run_worker(uv_loop_t *loop, struct engine *engine, fd_array_t *ipc_se
fflush(stdout);
uv_pipe_open(&pipe, 0);
uv_read_start((uv_stream_t*) &pipe, tty_alloc, tty_read);
} else {
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) {
uv_pipe_bind(&pipe, sock_file);
uv_listen((uv_stream_t *) &pipe, 16, tty_accept);
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) {
for (size_t i = 0; i < ipc_set->len; ++i) {
......@@ -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;
/* 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
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