<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>
<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>
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 = {
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;
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);
" -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,
ARG_FDNAME,
ARG_SEQPACKET,
ARG_INETD,
+ ARG_NOW,
};
static const struct option options[] = {
{ "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 },
{}
};
arg_inetd = true;
break;
+ case ARG_NOW:
+ arg_now = true;
+ break;
+
case '?':
return -EINVAL;
"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.");
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);