Browse Source

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.
master
Richard Nyberg 16 years ago
parent
commit
5a6ac5189f
2 changed files with 81 additions and 38 deletions
  1. +69
    -35
      btpd/main.c
  2. +12
    -3
      btpd/util.c

+ 69
- 35
btpd/main.c View File

@@ -1,73 +1,93 @@
#include "btpd.h" #include "btpd.h"


#include <sys/file.h>
#include <err.h>
#include <getopt.h> #include <getopt.h>
#include <time.h> #include <time.h>


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 static void
writepid(int pidfd) writepid(int pidfd)
{ {
FILE *fp = fdopen(dup(pidfd), "w"); int nw;
fprintf(fp, "%ld", (long)getpid()); char pidtxt[100];
fclose(fp); nw = snprintf(pidtxt, sizeof(pidtxt), "%ld", (long)getpid);
ftruncate(pidfd, 0);
write(pidfd, pidtxt, nw);
} }


static void static void
setup_daemon(int daemonize, const char *dir, const char *log) setup_daemon(int daemonize, const char *dir)
{ {
char c;
int pidfd; int pidfd;
pid_t pid;
struct timespec ts; struct timespec ts;


if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) 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)); strerror(errno));


if (log == NULL)
log = "log";

if (dir == NULL) { if (dir == NULL) {
if ((dir = find_btpd_dir()) == NULL) if ((dir = find_btpd_dir()) == NULL)
errx(1, "Cannot find the btpd directory"); btpd_err("Cannot find the btpd directory.\n");
else if (dir[0] != '/') if (dir[0] != '/')
errx(1, "got non absolute path '%s' from system environment.", btpd_err("Got non absolute path '%s' from system environment.\n",
dir); dir);
btpd_dir = dir; btpd_dir = dir;
} }


if (mkdir(dir, 0777) == -1 && errno != EEXIST) 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) 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) if (mkdir("torrents", 0777) == -1 && errno != EEXIST)
err(1, "Couldn't create torrents subdir"); btpd_err("Couldn't create torrents subdir (%s).\n", strerror(errno));

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);


if (btpd_dir == NULL) { if (btpd_dir == NULL) {
char wd[PATH_MAX]; char wd[PATH_MAX];
if (getcwd(wd, PATH_MAX) == NULL) if (getcwd(wd, PATH_MAX) == NULL)
err(1, "couldn't get working directory"); btpd_err("Couldn't get working directory (%s).\n",
btpd_dir = strdup(wd); strerror(errno));
if ((btpd_dir = strdup(wd)) == NULL)
btpd_err("Out of memory.\n");
} }


if (daemonize) { if (daemonize) {
if (daemon(1, 1) != 0) if (pipe(first_btpd_comm) < 0)
err(1, "Failed to daemonize"); btpd_err("Failed to create pipe (%s).\n", strerror(errno));
freopen("/dev/null", "r", stdin); if ((pid = fork()) < 0)
if (freopen(log, "a", stdout) == NULL) btpd_err("fork() failed (%s).\n", strerror(errno));
err(1, "Couldn't open '%s'", log); if (pid != 0) {
dup2(fileno(stdout), fileno(stderr)); read(first_btpd_comm[0], &c, 1);
setlinebuf(stdout); exit(c);
setlinebuf(stderr); }
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); writepid(pidfd);
} }


@@ -203,10 +223,11 @@ main(int argc, char **argv)
case 1: case 1:
break; break;
case 0: case 0:
errx(1, "You must specify a dotted IPv4 address.\n"); btpd_err("You must specify a dotted IPv4 address.\n");
break; break;
default: default:
err(1, "inet_ntop %s", optarg); btpd_err("inet_ntop for '%s' failed (%s).\n", optarg,
strerror(errno));
} }
break; break;
default: default:
@@ -225,13 +246,26 @@ args_done:
if (argc > 0) if (argc > 0)
usage(); usage();


setup_daemon(daemonize, dir, log); setup_daemon(daemonize, dir);


if (evloop_init() != 0) if (evloop_init() != 0)
btpd_err("Failed to initialize evloop (%s).\n", strerror(errno)); btpd_err("Failed to initialize evloop (%s).\n", strerror(errno));


btpd_init(); 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(); evloop();


btpd_err("Exit from evloop with error (%s).\n", strerror(errno)); btpd_err("Exit from evloop with error (%s).\n", strerror(errno));


+ 12
- 3
btpd/util.c View File

@@ -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 void
btpd_err(const char *fmt, ...) btpd_err(const char *fmt, ...)
{ {
va_list ap; va_list ap;
va_start(ap, fmt); va_start(ap, fmt);
log_common(BTPD_L_ERROR, fmt, ap); if (btpd_daemon_phase > 0) {
va_end(ap); vprintf(fmt, ap);
exit(1); if (btpd_daemon_phase == 1)
first_btpd_exit(1);
exit(1);
} else {
log_common(BTPD_L_ERROR, fmt, ap);
abort();
}
} }


void void


||||||
x
 
000:0
Loading…
Cancel
Save