diff --git a/man/systemd-socket-activate.xml b/man/systemd-socket-activate.xml index 4c29fa2c66..09f0d5cad6 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 e62b762c95..a80080b9cd 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,15 +509,17 @@ 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);