Ensure "tinc start" knows if the daemon really started succesfully.
authorGuus Sliepen <guus@tinc-vpn.org>
Wed, 20 May 2015 14:59:43 +0000 (16:59 +0200)
committerGuus Sliepen <guus@tinc-vpn.org>
Wed, 20 May 2015 14:59:43 +0000 (16:59 +0200)
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
src/logger.h
src/tincctl.c
src/tincd.c

index 2defb23..8fbd344 100644 (file)
@@ -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) {
index 8f69029..252497b 100644 (file)
@@ -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)));
index 46bf5bd..c6d4aac 100644 (file)
@@ -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;
        }
index fb2a155..b62c8c1 100644 (file)
@@ -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();