From: Guus Sliepen Date: Wed, 20 May 2015 14:59:43 +0000 (+0200) Subject: Ensure "tinc start" knows if the daemon really started succesfully. X-Git-Tag: release-1.1pre12~136 X-Git-Url: https://git.tinc-vpn.org/git/browse?a=commitdiff_plain;h=11868b890d1a7f4cfbfb37099393b32019010f66;p=tinc 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. --- diff --git a/src/logger.c b/src/logger.c index 2defb239..8fbd3448 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 8f690290..252497bf 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 46bf5bd5..c6d4aac5 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 fb2a1557..b62c8c19 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();