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.
This commit is contained in:
parent
7f96ef081d
commit
11868b890d
4 changed files with 58 additions and 3 deletions
|
@ -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) {
|
||||
|
|
|
@ -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)));
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
14
src/tincd.c
14
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();
|
||||
|
|
Loading…
Reference in a new issue