From: Daniel Foster Date: Mon, 26 May 2025 15:08:38 +0000 (+1000) Subject: socket-activate: add --now option X-Git-Tag: v258-rc1~318^2~1 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=9e940164e9343aec156d0ae97c9358f468caae77;p=thirdparty%2Fsystemd.git socket-activate: add --now option Add a --now option that starts the program instantly, instead of waiting for a connection on the socket. This is useful, for instance, when developing: Say I have a Rust, socket-activated web service. I can test it with: systemd-socket-activate -l 8080 --fdname=http cargo run However this delays running the service (which potentially involves compilation) to when I try to connect to it, which wastes time. Since it delays compilation, I also don't see any warning or errors in the code until it gets a connection either. The name's now a bit of a misnomer, since starting the service immediately isn't really socket activation, but oh well ¯\_(ツ)_/⁻ --- diff --git a/man/systemd-socket-activate.xml b/man/systemd-socket-activate.xml index 4c29fa2c665..09f0d5cad60 100644 --- a/man/systemd-socket-activate.xml +++ b/man/systemd-socket-activate.xml @@ -72,7 +72,7 @@ Launch an instance of the service program for each connection and pass the connection - socket. + socket. May not be combined with . @@ -135,6 +135,16 @@ + + + + Start the service program instantly, instead of waiting for a connection on the + socket(s). May not be combined with . + + + + + diff --git a/src/socket-activate/socket-activate.c b/src/socket-activate/socket-activate.c index e62b762c950..a80080b9cd0 100644 --- a/src/socket-activate/socket-activate.c +++ b/src/socket-activate/socket-activate.c @@ -30,6 +30,7 @@ static int arg_socket_type = SOCK_STREAM; static char **arg_setenv = NULL; static char **arg_fdnames = NULL; static bool arg_inetd = false; +static bool arg_now = false; static int add_epoll(int epoll_fd, int fd) { struct epoll_event ev = { @@ -117,9 +118,11 @@ static int open_sockets(int *ret_epoll_fd) { log_warning("More than one fd name specified with --accept."); } - epoll_fd = epoll_create1(EPOLL_CLOEXEC); - if (epoll_fd < 0) - return log_error_errno(errno, "Failed to create epoll object: %m"); + if (!arg_now) { + epoll_fd = epoll_create1(EPOLL_CLOEXEC); + if (epoll_fd < 0) + return log_error_errno(errno, "Failed to create epoll object: %m"); + } for (int fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + count; fd++) { _cleanup_free_ char *name = NULL; @@ -127,9 +130,11 @@ static int open_sockets(int *ret_epoll_fd) { getsockname_pretty(fd, &name); log_info("Listening on %s as %i.", strna(name), fd); - r = add_epoll(epoll_fd, fd); - if (r < 0) - return r; + if (epoll_fd >= 0) { + r = add_epoll(epoll_fd, fd); + if (r < 0) + return r; + } } *ret_epoll_fd = TAKE_FD(epoll_fd); @@ -323,6 +328,7 @@ static int help(void) { " -E --setenv=NAME[=VALUE] Pass an environment variable to children\n" " --fdname=NAME[:NAME...] Specify names for file descriptors\n" " --inetd Enable inetd file descriptor passing protocol\n" + " --now Start instantly instead of waiting for connection\n" "\nNote: file descriptors from sd_listen_fds() will be passed through.\n" "\nSee the %s for details.\n", program_invocation_short_name, @@ -339,6 +345,7 @@ static int parse_argv(int argc, char *argv[]) { ARG_FDNAME, ARG_SEQPACKET, ARG_INETD, + ARG_NOW, }; static const struct option options[] = { @@ -352,6 +359,7 @@ static int parse_argv(int argc, char *argv[]) { { "environment", required_argument, NULL, 'E' }, /* legacy alias */ { "fdname", required_argument, NULL, ARG_FDNAME }, { "inetd", no_argument, NULL, ARG_INETD }, + { "now", no_argument, NULL, ARG_NOW }, {} }; @@ -432,6 +440,10 @@ static int parse_argv(int argc, char *argv[]) { arg_inetd = true; break; + case ARG_NOW: + arg_now = true; + break; + case '?': return -EINVAL; @@ -449,6 +461,10 @@ static int parse_argv(int argc, char *argv[]) { "Datagram sockets do not accept connections. " "The --datagram and --accept options may not be combined."); + if (arg_accept && arg_now) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "--now cannot be used in conjunction with --accept."); + if (arg_fdnames && arg_inetd) log_warning("--fdname= has no effect with --inetd present."); @@ -493,14 +509,16 @@ static int run(int argc, char **argv) { for (;;) { struct epoll_event event; - if (epoll_wait(epoll_fd, &event, 1, -1) < 0) { - if (errno == EINTR) - continue; + if (epoll_fd >= 0) { + if (epoll_wait(epoll_fd, &event, 1, -1) < 0) { + if (errno == EINTR) + continue; - return log_error_errno(errno, "epoll_wait() failed: %m"); - } + return log_error_errno(errno, "epoll_wait() failed: %m"); + } - log_info("Communication attempt on fd %i.", event.data.fd); + log_info("Communication attempt on fd %i.", event.data.fd); + } if (!arg_accept) return exec_process(exec_argv, SD_LISTEN_FDS_START, (size_t) n);