Skip to content

Commit

Permalink
supervise-daemon: add s6-style readiness notification.
Browse files Browse the repository at this point in the history
  • Loading branch information
navi-desu committed Jan 5, 2025
1 parent da04d1c commit a6d66bf
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 2 deletions.
1 change: 1 addition & 0 deletions sh/supervise-daemon.sh
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ supervise_start()
${no_new_privs:+--no-new-privs} \
${command_user+--user} $command_user \
${umask+--umask} $umask \
${ready+--ready} $ready \
${supervise_daemon_args-${start_stop_daemon_args}} \
$command \
-- $command_args $command_args_foreground
Expand Down
45 changes: 43 additions & 2 deletions src/supervise-daemon/supervise-daemon.c
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ enum {
LONGOPT_SECBITS,
LONGOPT_STDERR_LOGGER,
LONGOPT_STDOUT_LOGGER,
LONGOPT_READY,
};

const char *applet = NULL;
Expand Down Expand Up @@ -115,6 +116,7 @@ const struct option longopts[] = {
{ "stderr", 1, NULL, '2'},
{ "stdout-logger",1, NULL, LONGOPT_STDOUT_LOGGER},
{ "stderr-logger",1, NULL, LONGOPT_STDERR_LOGGER},
{ "ready", 1, NULL, LONGOPT_READY},
{ "reexec", 0, NULL, '3'},
longopts_COMMON
};
Expand Down Expand Up @@ -165,6 +167,8 @@ static int devnull_fd = -1;
static int stdin_fd;
static int stdout_fd;
static int stderr_fd;
static int ready_fd = -1;
static int ready_pipe[2];
static char *redirect_stderr = NULL;
static char *redirect_stdout = NULL;
static char *stderr_process = NULL;
Expand Down Expand Up @@ -588,6 +592,9 @@ RC_NORETURN static void child_process(char *exec, char **argv)

cloexec_fds_from(3);

if (ready_fd != -1)
dup2(ready_pipe[1], ready_fd);

cmdline = make_cmdline(argv);
syslog(LOG_INFO, "Child command line: %s", cmdline);
free(cmdline);
Expand Down Expand Up @@ -786,6 +793,28 @@ RC_NORETURN static void supervisor(char *exec, char **argv)
exit(EXIT_SUCCESS);
}

static void wait_ready(void)
{
if (ready_fd == -1)
exit(EXIT_SUCCESS);

close(ready_pipe[1]);
/* TODO: add timeout failure and stop child supervisor */
for (;;) {
char buf[BUFSIZ];
int bytes = read(ready_pipe[0], buf, BUFSIZ);
if (bytes == -1 && errno != EINTR) {
eerror("%s: read failed '%s'\n", applet, strerror(errno));
exit(EXIT_FAILURE);
}

if (memchr(buf, '\n', bytes))
break;
}

exit(EXIT_SUCCESS);
}

int main(int argc, char **argv)
{
int opt;
Expand Down Expand Up @@ -1068,6 +1097,12 @@ int main(int argc, char **argv)
stderr_process = optarg;
break;

case LONGOPT_READY:
if (sscanf(optarg, "fd:%d", &ready_fd) != 1)
eerrorx("%s: invalid ready '%s'.", applet, optarg);
pipe(ready_pipe);
break;

case_RC_COMMON_GETOPT
}

Expand Down Expand Up @@ -1205,19 +1240,25 @@ int main(int argc, char **argv)
if (child_pid == -1)
eerrorx("%s: fork: %s", applet, strerror(errno));
if (child_pid != 0)
/* first parent process, do nothing. */
exit(EXIT_SUCCESS);
wait_ready();

#ifdef TIOCNOTTY
tty_fd = open("/dev/tty", O_RDWR);
#endif
devnull_fd = open("/dev/null", O_RDWR);
dup2(devnull_fd, STDIN_FILENO);
dup2(devnull_fd, STDOUT_FILENO);
dup2(devnull_fd, STDERR_FILENO);

if (ready_fd != -1)
close(ready_pipe[0]);

child_pid = fork();
if (child_pid == -1)
eerrorx("%s: fork: %s", applet, strerror(errno));
else if (child_pid != 0) {
if (ready_fd != -1)
close(ready_pipe[1]);
c = argv;
x = 0;
while (c && *c) {
Expand Down

0 comments on commit a6d66bf

Please sign in to comment.