X-Git-Url: http://jsfdemo.indexdata.com/?a=blobdiff_plain;f=src%2Fprocess.c;h=e3e8a4a7f82f92e05b8ede8c5f438f08ed563f0d;hb=d5ffc2f6e667c1d849bf7579add8435664e678c5;hp=4f7ce9418c36d7f239ce8e1460f3310a52c49fd0;hpb=2dcca58dcfd42a54b98f413a2bbb8676e05302d4;p=pazpar2-moved-to-github.git diff --git a/src/process.c b/src/process.c index 4f7ce94..e3e8a4a 100644 --- a/src/process.c +++ b/src/process.c @@ -1,4 +1,4 @@ -/* $Id: process.c,v 1.2 2007-06-12 13:02:38 adam Exp $ +/* $Id: process.c,v 1.4 2007-06-18 11:44:43 adam Exp $ Copyright (c) 2006-2007, Index Data. This file is part of Pazpar2. @@ -24,30 +24,38 @@ Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA #endif #include +#include #include #include #include #include #include #include +#include +#include #include #include - +#include #include "pazpar2.h" -static void write_pidfile(const char *pidfile) +static void write_pidfile(int pid_fd) { - if (pidfile) + if (pid_fd != -1) { - FILE *f = fopen(pidfile, "w"); - if (!f) + char buf[40]; + yaz_snprintf(buf, sizeof(buf), "%ld", (long) getpid()); + if (ftruncate(pid_fd, 0)) { - yaz_log(YLOG_ERRNO|YLOG_FATAL, "Couldn't create %s", pidfile); - exit(0); + yaz_log(YLOG_FATAL|YLOG_ERRNO, "ftruncate"); + exit(1); } - fprintf(f, "%ld", (long) getpid()); - fclose(f); + if (write(pid_fd, buf, strlen(buf)) != strlen(buf)) + { + yaz_log(YLOG_FATAL|YLOG_ERRNO, "write"); + exit(1); + } + close(pid_fd); } } @@ -58,43 +66,103 @@ void kill_child_handler(int num) kill(child_pid, num); } -int pazpar2_process(int debug, +int pazpar2_process(int debug, int daemon, void (*work)(void *data), void *data, const char *pidfile, const char *uid /* not yet used */) { - struct passwd *pw = 0; int run = 1; int cont = 1; void (*old_sighup)(int); void (*old_sigterm)(int); + int pid_fd = -1; + /* open pidfile .. defer write until in child and after setuid */ + if (pidfile) + { + pid_fd = open(pidfile, O_CREAT|O_RDWR, 0666); + if (pid_fd == -1) + { + yaz_log(YLOG_FATAL|YLOG_ERRNO, "open %s", pidfile); + exit(1); + } + } if (debug) { /* in debug mode.. it's quite simple */ - write_pidfile(pidfile); + write_pidfile(pid_fd); work(data); exit(0); } - + /* running in production mode. */ if (uid) { - yaz_log(YLOG_LOG, "getpwnam"); - // OK to use the non-thread version here - if (!(pw = getpwnam(uid))) + /* OK to use the non-thread version here */ + struct passwd *pw = getpwnam(uid); + if (!pw) { yaz_log(YLOG_FATAL, "%s: Unknown user", uid); exit(1); } + if (setuid(pw->pw_uid) < 0) + { + yaz_log(YLOG_FATAL|YLOG_ERRNO, "setuid"); + exit(1); + } + } + + if (daemon) + { + /* create pipe so that parent waits until child has created + PID (or failed) */ + static int hand[2]; /* hand shake for child */ + if (pipe(hand) < 0) + { + yaz_log(YLOG_FATAL|YLOG_ERRNO, "pipe"); + return 1; + } + switch (fork()) + { + case 0: + break; + case -1: + return 1; + default: + close(hand[1]); + while(1) + { + char dummy[1]; + int res = read(hand[0], dummy, 1); + if (res < 0 && errno != EINTR) + { + yaz_log(YLOG_FATAL|YLOG_ERRNO, "read fork handshake"); + break; + } + else if (res >= 0) + break; + } + close(hand[0]); + _exit(0); + } + /* child */ + close(hand[0]); + if (setsid() < 0) + return 1; + + close(0); + close(1); + close(2); + open("/dev/null", O_RDWR); + dup(0); dup(0); + close(hand[1]); } - + + write_pidfile(pid_fd); /* keep signals in their original state and make sure that some signals - to parent process also gets sent to the child.. Normally this - should not happen. We want the _child_ process to be terminated - normally. However, if the parent process is terminated, we - kill the child too */ + to parent process also gets sent to the child.. + */ old_sighup = signal(SIGHUP, kill_child_handler); old_sigterm = signal(SIGTERM, kill_child_handler); while (cont) @@ -114,17 +182,6 @@ int pazpar2_process(int debug, signal(SIGHUP, old_sighup); /* restore */ signal(SIGTERM, old_sigterm);/* restore */ - write_pidfile(pidfile); - - if (pw) - { - if (setuid(pw->pw_uid) < 0) - { - yaz_log(YLOG_FATAL|YLOG_ERRNO, "setuid"); - exit(1); - } - } - work(data); exit(0); } @@ -133,7 +190,6 @@ int pazpar2_process(int debug, child_pid = p; p1 = wait(&status); - yaz_log_reopen(); /* disable signalling in kill_child_handler */ child_pid = 0;