From 5a6ac5189fc438e359ecf0bebaedd70c1af03fdd Mon Sep 17 00:00:00 2001 From: Richard Nyberg Date: Mon, 12 Jan 2009 23:50:01 +0100 Subject: [PATCH] Let the initial process linger until the daemon is initialized. This enables us to report errors in the btpd init sequence to the shell by non zero exit code. Changed from flock to lockf because of solaris troubles. I may be confused though. --- btpd/main.c | 104 ++++++++++++++++++++++++++++++++++------------------ btpd/util.c | 15 ++++++-- 2 files changed, 81 insertions(+), 38 deletions(-) diff --git a/btpd/main.c b/btpd/main.c index c43c223..089929d 100644 --- a/btpd/main.c +++ b/btpd/main.c @@ -1,73 +1,93 @@ #include "btpd.h" -#include -#include #include #include +int btpd_daemon_phase = 2; +int first_btpd_comm[2]; + +void +first_btpd_exit(char code) +{ + write(first_btpd_comm[1], &code, 1); + close(first_btpd_comm[0]); + close(first_btpd_comm[1]); +} + static void writepid(int pidfd) { - FILE *fp = fdopen(dup(pidfd), "w"); - fprintf(fp, "%ld", (long)getpid()); - fclose(fp); + int nw; + char pidtxt[100]; + nw = snprintf(pidtxt, sizeof(pidtxt), "%ld", (long)getpid); + ftruncate(pidfd, 0); + write(pidfd, pidtxt, nw); } static void -setup_daemon(int daemonize, const char *dir, const char *log) +setup_daemon(int daemonize, const char *dir) { + char c; int pidfd; + pid_t pid; struct timespec ts; if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) - errx(1, "clock_gettime(CLOCK_MONOTONIC, ...) error (%s).", + btpd_err("clock_gettime(CLOCK_MONOTONIC, ...) failed (%s).\n", strerror(errno)); - if (log == NULL) - log = "log"; - if (dir == NULL) { if ((dir = find_btpd_dir()) == NULL) - errx(1, "Cannot find the btpd directory"); - else if (dir[0] != '/') - errx(1, "got non absolute path '%s' from system environment.", + btpd_err("Cannot find the btpd directory.\n"); + if (dir[0] != '/') + btpd_err("Got non absolute path '%s' from system environment.\n", dir); btpd_dir = dir; } if (mkdir(dir, 0777) == -1 && errno != EEXIST) - err(1, "Couldn't create home '%s'", dir); + btpd_err("Couldn't create home '%s' (%s).\n", dir, strerror(errno)); if (chdir(dir) != 0) - err(1, "Couldn't change working directory to '%s'", dir); + btpd_err("Couldn't change working directory to '%s' (%s).\n", dir, + strerror(errno)); if (mkdir("torrents", 0777) == -1 && errno != EEXIST) - err(1, "Couldn't create torrents subdir"); - - if ((pidfd = open("pid", O_CREAT|O_TRUNC|O_WRONLY, 0666)) == -1) - err(1, "Couldn't open 'pid'"); - - if (flock(pidfd, LOCK_NB|LOCK_EX) == -1) - errx(1, "Another instance of btpd is probably running in %s.", dir); + btpd_err("Couldn't create torrents subdir (%s).\n", strerror(errno)); if (btpd_dir == NULL) { char wd[PATH_MAX]; if (getcwd(wd, PATH_MAX) == NULL) - err(1, "couldn't get working directory"); - btpd_dir = strdup(wd); + btpd_err("Couldn't get working directory (%s).\n", + strerror(errno)); + if ((btpd_dir = strdup(wd)) == NULL) + btpd_err("Out of memory.\n"); } if (daemonize) { - if (daemon(1, 1) != 0) - err(1, "Failed to daemonize"); - freopen("/dev/null", "r", stdin); - if (freopen(log, "a", stdout) == NULL) - err(1, "Couldn't open '%s'", log); - dup2(fileno(stdout), fileno(stderr)); - setlinebuf(stdout); - setlinebuf(stderr); + if (pipe(first_btpd_comm) < 0) + btpd_err("Failed to create pipe (%s).\n", strerror(errno)); + if ((pid = fork()) < 0) + btpd_err("fork() failed (%s).\n", strerror(errno)); + if (pid != 0) { + read(first_btpd_comm[0], &c, 1); + exit(c); + } + btpd_daemon_phase--; + if (setsid() < 0) + btpd_err("setsid() failed (%s).\n", strerror(errno)); + if ((pid = fork()) < 0) + btpd_err("fork() failed (%s).\n", strerror(errno)); + if (pid != 0) + exit(0); } + if ((pidfd = open("pid", O_CREAT|O_WRONLY, 0666)) == -1) + btpd_err("Couldn't open 'pid' (%s).\n", strerror(errno)); + + if (lockf(pidfd, F_TLOCK, 0) == -1) + btpd_err("Another instance of btpd is probably running in %s.\n", dir); + writepid(pidfd); } @@ -203,10 +223,11 @@ main(int argc, char **argv) case 1: break; case 0: - errx(1, "You must specify a dotted IPv4 address.\n"); + btpd_err("You must specify a dotted IPv4 address.\n"); break; default: - err(1, "inet_ntop %s", optarg); + btpd_err("inet_ntop for '%s' failed (%s).\n", optarg, + strerror(errno)); } break; default: @@ -225,13 +246,26 @@ args_done: if (argc > 0) usage(); - setup_daemon(daemonize, dir, log); + setup_daemon(daemonize, dir); if (evloop_init() != 0) btpd_err("Failed to initialize evloop (%s).\n", strerror(errno)); btpd_init(); + if (daemonize) { + if (freopen("/dev/null", "r", stdin) == NULL) + btpd_err("freopen of stdin failed (%s).\n", strerror(errno)); + if (freopen(log == NULL ? "log" : log, "a", stderr) == NULL) + btpd_err("Couldn't open '%s' (%s).\n", log, strerror(errno)); + if (dup2(fileno(stderr), fileno(stdout)) < 0) + btpd_err("dup2 failed (%s).\n", strerror(errno)); + first_btpd_exit(0); + } + setlinebuf(stdout); + setlinebuf(stderr); + + btpd_daemon_phase = 0; evloop(); btpd_err("Exit from evloop with error (%s).\n", strerror(errno)); diff --git a/btpd/util.c b/btpd/util.c index c6b430e..02ce032 100644 --- a/btpd/util.c +++ b/btpd/util.c @@ -91,14 +91,23 @@ log_common(uint32_t type, const char *fmt, va_list ap) } } +extern int btpd_daemon_phase; +extern void first_btpd_exit(char); + void btpd_err(const char *fmt, ...) { va_list ap; va_start(ap, fmt); - log_common(BTPD_L_ERROR, fmt, ap); - va_end(ap); - exit(1); + if (btpd_daemon_phase > 0) { + vprintf(fmt, ap); + if (btpd_daemon_phase == 1) + first_btpd_exit(1); + exit(1); + } else { + log_common(BTPD_L_ERROR, fmt, ap); + abort(); + } } void