*
* \sa fork(2), setsid(2), dup(2).
*/
-void daemon_init(void)
+int daemon_init(void)
{
pid_t pid;
- int null;
+ int null, fd[2];
DSS_INFO_LOG(("daemonizing\n"));
+ if (pipe(fd) < 0)
+ goto err;
pid = fork();
if (pid < 0)
goto err;
- if (pid)
- exit(EXIT_SUCCESS); /* parent exits */
+ if (pid) {
+ /*
+ * The parent process exits once it has received one byte from
+ * the reading end of the pipe. If the child exits before it
+ * was able to complete its setup (acquire the lock on the
+ * semaphore), the read() below will return zero. In this case
+ * we let the parent die unsuccessfully.
+ */
+ char c;
+ int ret;
+ close(fd[1]);
+ ret = read(fd[0], &c, 1);
+ if (ret <= 0) {
+ DSS_EMERG_LOG(("child terminated unexpectedly\n"));
+ exit(EXIT_FAILURE);
+ }
+ exit(EXIT_SUCCESS);
+ }
+ close(fd[0]);
/* become session leader */
if (setsid() < 0)
goto err;
if (dup2(null, STDERR_FILENO) < 0)
goto err;
close(null);
- return;
+ return fd[1];
err:
DSS_EMERG_LOG(("fatal: %s\n", strerror(errno)));
exit(EXIT_FAILURE);
/** \file daemon.h exported symbols from daemon.c */
-void daemon_init(void);
+int daemon_init(void);
FILE *open_log(const char *logfile_name);
void close_log(FILE* logfile);
void log_welcome(int loglevel);
static int com_run(void)
{
- int ret;
+ int ret, fd = -1;
if (OPT_GIVEN(DSS, DRY_RUN)) {
DSS_ERROR_LOG(("dry run not supported by this command\n"));
return -E_SYNTAX;
}
if (OPT_GIVEN(RUN, DAEMON)) {
- daemon_init();
+ fd = daemon_init();
daemonized = true;
logfile = open_log(OPT_STRING_VAL(RUN, LOGFILE));
}
ret = install_sighandler(SIGHUP);
if (ret < 0)
return ret;
+ if (fd >= 0) {
+ ret = write(fd, "\0", 1);
+ if (ret != 1) {
+ DSS_ERROR_LOG(("write to daemon pipe returned %d\n",
+ ret));
+ if (ret < 0)
+ return -ERRNO_TO_DSS_ERROR(errno);
+ return -E_BUG;
+ }
+ }
ret = select_loop();
if (ret >= 0) /* impossible */
ret = -E_BUG;