X-Git-Url: http://jsfdemo.indexdata.com/?a=blobdiff_plain;f=src%2Fprocess.c;h=e3e8a4a7f82f92e05b8ede8c5f438f08ed563f0d;hb=414a47e2db4d91f3733d6ac48c1a5f14c00ced12;hp=9a97da7877c63442618888511873274be2e9bf0f;hpb=1853168ac9b85627a95a8067ef5c6cdc9f82b16d;p=pazpar2-moved-to-github.git diff --git a/src/process.c b/src/process.c index 9a97da7..e3e8a4a 100644 --- a/src/process.c +++ b/src/process.c @@ -1,4 +1,4 @@ -/* $Id: process.c,v 1.1 2007-06-08 13:57:19 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,28 +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); } } @@ -56,7 +66,7 @@ void kill_child_handler(int num) kill(child_pid, num); } -int pazpar2_process(int debug, int flags, +int pazpar2_process(int debug, int daemon, void (*work)(void *data), void *data, const char *pidfile, const char *uid /* not yet used */) { @@ -64,22 +74,95 @@ int pazpar2_process(int debug, int flags, 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) + { + /* 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) @@ -99,7 +182,6 @@ int pazpar2_process(int debug, int flags, signal(SIGHUP, old_sighup); /* restore */ signal(SIGTERM, old_sigterm);/* restore */ - write_pidfile(pidfile); work(data); exit(0); } @@ -108,7 +190,6 @@ int pazpar2_process(int debug, int flags, child_pid = p; p1 = wait(&status); - yaz_log_reopen(); /* disable signalling in kill_child_handler */ child_pid = 0; @@ -153,9 +234,9 @@ int pazpar2_process(int debug, int flags, else if (status == 0) cont = 0; /* child exited normally */ else - { /* child exited in an abnormal way */ + { /* child exited with error */ yaz_log(YLOG_LOG, "Exit %d from child %ld", status, (long) p); - cont = 1; + cont = 0; } if (cont) /* respawn slower as we get more errors */ sleep(1 + run/5);