mirror of
https://github.com/morgan9e/systemd
synced 2026-04-15 00:47:10 +09:00
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 ¯\_(ツ)_/⁻
This commit is contained in:
@@ -72,7 +72,7 @@
|
||||
<term><option>--accept</option></term>
|
||||
|
||||
<listitem><para>Launch an instance of the service program for each connection and pass the connection
|
||||
socket.</para>
|
||||
socket. May not be combined with <option>--now</option>.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v230"/></listitem>
|
||||
</varlistentry>
|
||||
@@ -135,6 +135,16 @@
|
||||
<xi:include href="version-info.xml" xpointer="v230"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--now</option></term>
|
||||
|
||||
<listitem><para>Start the service program instantly, instead of waiting for a connection on the
|
||||
socket(s). May not be combined with <option>--accept</option>.
|
||||
</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v258"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<xi:include href="standard-options.xml" xpointer="help" />
|
||||
<xi:include href="standard-options.xml" xpointer="version" />
|
||||
</variablelist>
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user