diff --git a/logging.c b/logging.c index 6342421..25378e8 100644 --- a/logging.c +++ b/logging.c @@ -41,6 +41,8 @@ static int initialised = 0; static int system_log = 0; +static int parent_fd = 0; + static time_t last_limited = 0; #ifdef WINNT @@ -154,6 +156,9 @@ LOG_Fatal_Function(LOG_Facility facility, const char *format, ...) } else { fprintf(stderr, "Fatal error : %s\n", buf); } + if (parent_fd) { + write(parent_fd, buf, strlen(buf) + 1); + } #endif MAI_CleanupAndExit(); @@ -196,6 +201,23 @@ LOG_OpenSystemLog(void) /* ================================================== */ +void +LOG_SetParentFd(int fd) +{ + parent_fd = fd; +} + +/* ================================================== */ + +void +LOG_CloseParentFd() +{ + if (parent_fd > 0) + close(parent_fd); +} + +/* ================================================== */ + int LOG_RateLimited(void) { diff --git a/logging.h b/logging.h index 5038cc8..b927eaa 100644 --- a/logging.h +++ b/logging.h @@ -85,6 +85,12 @@ extern void LOG_Position(const char *filename, int line_number, const char *func /* Log messages to syslog instead of stderr */ extern void LOG_OpenSystemLog(void); +/* Send fatal message also to the foreground process */ +extern void LOG_SetParentFd(int fd); + +/* Close the pipe to the foreground process so it can exit */ +extern void LOG_CloseParentFd(void); + /* Return zero once per 10 seconds */ extern int LOG_RateLimited(void); diff --git a/main.c b/main.c index e68846e..3bf02aa 100644 --- a/main.c +++ b/main.c @@ -124,6 +124,8 @@ signal_cleanup(int x) static void post_acquire_hook(void *anything) { + /* Close the pipe to the foreground process so it can exit */ + LOG_CloseParentFd(); CNF_AddSources(); CNF_AddBroadcasts(); @@ -214,7 +216,13 @@ go_daemon(void) #else - int pid, fd; + int pid, fd, pipefd[2]; + + /* Create pipe which will the daemon use to notify the grandparent + when it's initialised or send an error message */ + if (pipe(pipefd)) { + LOG(LOGS_ERR, LOGF_Logging, "Could not detach, pipe failed : %s", strerror(errno)); + } /* Does this preserve existing signal handlers? */ pid = fork(); @@ -222,8 +230,22 @@ go_daemon(void) if (pid < 0) { LOG(LOGS_ERR, LOGF_Logging, "Could not detach, fork failed : %s", strerror(errno)); } else if (pid > 0) { - exit(0); /* In the 'grandparent' */ + /* In the 'grandparent' */ + char message[1024]; + int r; + + close(pipefd[1]); + r = read(pipefd[0], message, sizeof (message)); + if (r) { + if (r > 0) { + /* Print the error message from the child */ + fprintf(stderr, "%.1024s\n", message); + } + exit(1); + } else + exit(0); } else { + close(pipefd[0]); setsid(); @@ -237,13 +259,17 @@ go_daemon(void) } else { /* In the child we want to leave running as the daemon */ - /* Don't keep stdin/out/err from before. */ + /* Don't keep stdin/out/err from before. But don't close + the parent pipe yet. */ for (fd=0; fd<1024; fd++) { - close(fd); + if (fd != pipefd[1]) + close(fd); } /* Change current directory to / */ chdir("/"); + + LOG_SetParentFd(pipefd[1]); } } @@ -331,7 +357,6 @@ int main if (maybe_another_chronyd_running(&other_pid)) { LOG_FATAL(LOGF_Main, "Another chronyd may already be running (pid=%d), check lockfile (%s)", other_pid, CNF_GetPidFile()); - exit(1); } /* Write our lockfile to prevent other chronyds running. This has *GOT* to