From 11868b890d1a7f4cfbfb37099393b32019010f66 Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Wed, 20 May 2015 16:59:43 +0200 Subject: [PATCH] Ensure "tinc start" knows if the daemon really started succesfully. We do this by creating an umbilical between the CLI and the daemon. The daemon pipes log messages to the CLI until it starts the main loop. The daemon then cuts the umbilical. The CLI copies all the received log messages to stderr, and the last byte indicates whether the daemon started succesfully or not, so the CLI can exit with a useful exit code. --- src/logger.c | 7 ++++++- src/logger.h | 1 + src/tincctl.c | 39 +++++++++++++++++++++++++++++++++++++-- src/tincd.c | 14 ++++++++++++++ 4 files changed, 58 insertions(+), 3 deletions(-) diff --git a/src/logger.c b/src/logger.c index 2defb23..8fbd344 100644 --- a/src/logger.c +++ b/src/logger.c @@ -37,7 +37,7 @@ static HANDLE loghandle = NULL; #endif static const char *logident = NULL; bool logcontrol = false; - +int umbilical = 0; static void real_logger(int level, int priority, const char *message) { char timestr[32] = ""; @@ -79,6 +79,11 @@ static void real_logger(int level, int priority, const char *message) { case LOGMODE_NULL: break; } + + if(umbilical) { + write(umbilical, message, strlen(message)); + write(umbilical, "\n", 1); + } } if(logcontrol) { diff --git a/src/logger.h b/src/logger.h index 8f69029..252497b 100644 --- a/src/logger.h +++ b/src/logger.h @@ -69,6 +69,7 @@ enum { extern debug_t debug_level; extern bool logcontrol; +extern int umbilical; extern void openlogger(const char *, logmode_t); extern void reopenlogger(void); extern void logger(int, int, const char *, ...) __attribute__ ((__format__(printf, 3, 4))); diff --git a/src/tincctl.c b/src/tincctl.c index 46bf5bd..c6d4aac 100644 --- a/src/tincctl.c +++ b/src/tincctl.c @@ -853,6 +853,13 @@ static int cmd_start(int argc, char *argv[]) { } return status; #else + int pfd[2] = {-1, -1}; + if(pipe(pfd)) { + fprintf(stderr, "Could not create umbilical pipe: %s\n", strerror(errno)); + free(nargv); + return 1; + } + pid_t pid = fork(); if(pid == -1) { fprintf(stderr, "Could not fork: %s\n", strerror(errno)); @@ -860,8 +867,15 @@ static int cmd_start(int argc, char *argv[]) { return 1; } - if(!pid) + if(!pid) { + close(pfd[0]); + char buf[100] = ""; + snprintf(buf, sizeof buf, "%d", pfd[1]); + setenv("TINC_UMBILICAL", buf, true); exit(execvp(c, nargv)); + } else { + close(pfd[1]); + } free(nargv); @@ -869,12 +883,33 @@ static int cmd_start(int argc, char *argv[]) { #ifdef SIGINT signal(SIGINT, SIG_IGN); #endif + + // Pass all log messages from the umbilical to stderr. + // A nul-byte right before closure means tincd started succesfully. + bool failure = true; + char buf[1024]; + ssize_t len; + + while((len = read(pfd[0], buf, sizeof buf)) > 0) { + failure = buf[len - 1]; + if(!failure) + len--; + write(2, buf, len); + } + + if(len) + failure = true; + + close(pfd[0]); + + // Make sure the child process is really gone. result = waitpid(pid, &status, 0); + #ifdef SIGINT signal(SIGINT, SIG_DFL); #endif - if(result != pid || !WIFEXITED(status) || WEXITSTATUS(status)) { + if(failure || result != pid || !WIFEXITED(status) || WEXITSTATUS(status)) { fprintf(stderr, "Error starting %s\n", c); return 1; } diff --git a/src/tincd.c b/src/tincd.c index fb2a155..b62c8c1 100644 --- a/src/tincd.c +++ b/src/tincd.c @@ -363,6 +363,14 @@ int main(int argc, char **argv) { logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", "WSAStartup", winerror(GetLastError())); return 1; } +#else + // Check if we got an umbilical fd from the process that started us + char *umbstr = getenv("TINC_UMBILICAL"); + if(umbstr) { + umbilical = atoi(umbstr); + if(fcntl(umbilical, F_GETFL) < 0) + umbilical = 0; + } #endif openlogger("tinc", use_logfile?LOGMODE_FILE:LOGMODE_STDERR); @@ -466,6 +474,12 @@ int main2(int argc, char **argv) { logger(DEBUG_ALWAYS, LOG_NOTICE, "Ready"); + if(umbilical) { // snip! + write(umbilical, "", 1); + close(umbilical); + umbilical = 0; + } + try_outgoing_connections(); status = main_loop(); -- 2.25.1