1 /* $Id: process.c,v 1.4 2007-06-18 11:44:43 adam Exp $
2 Copyright (c) 2006-2007, Index Data.
4 This file is part of Pazpar2.
6 Pazpar2 is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 2, or (at your option) any later
11 Pazpar2 is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 You should have received a copy of the GNU General Public License
17 along with Pazpar2; see the file LICENSE. If not, write to the
18 Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
33 #include <sys/types.h>
39 #include <yaz/snprintf.h>
42 static void write_pidfile(int pid_fd)
47 yaz_snprintf(buf, sizeof(buf), "%ld", (long) getpid());
48 if (ftruncate(pid_fd, 0))
50 yaz_log(YLOG_FATAL|YLOG_ERRNO, "ftruncate");
53 if (write(pid_fd, buf, strlen(buf)) != strlen(buf))
55 yaz_log(YLOG_FATAL|YLOG_ERRNO, "write");
63 void kill_child_handler(int num)
69 int pazpar2_process(int debug, int daemon,
70 void (*work)(void *data), void *data,
71 const char *pidfile, const char *uid /* not yet used */)
75 void (*old_sighup)(int);
76 void (*old_sigterm)(int);
79 /* open pidfile .. defer write until in child and after setuid */
82 pid_fd = open(pidfile, O_CREAT|O_RDWR, 0666);
85 yaz_log(YLOG_FATAL|YLOG_ERRNO, "open %s", pidfile);
92 /* in debug mode.. it's quite simple */
93 write_pidfile(pid_fd);
98 /* running in production mode. */
101 /* OK to use the non-thread version here */
102 struct passwd *pw = getpwnam(uid);
105 yaz_log(YLOG_FATAL, "%s: Unknown user", uid);
108 if (setuid(pw->pw_uid) < 0)
110 yaz_log(YLOG_FATAL|YLOG_ERRNO, "setuid");
117 /* create pipe so that parent waits until child has created
119 static int hand[2]; /* hand shake for child */
122 yaz_log(YLOG_FATAL|YLOG_ERRNO, "pipe");
136 int res = read(hand[0], dummy, 1);
137 if (res < 0 && errno != EINTR)
139 yaz_log(YLOG_FATAL|YLOG_ERRNO, "read fork handshake");
156 open("/dev/null", O_RDWR);
161 write_pidfile(pid_fd);
163 /* keep signals in their original state and make sure that some signals
164 to parent process also gets sent to the child..
166 old_sighup = signal(SIGHUP, kill_child_handler);
167 old_sigterm = signal(SIGTERM, kill_child_handler);
173 if (p == (pid_t) (-1))
176 yaz_log(YLOG_FATAL|YLOG_ERRNO, "fork");
182 signal(SIGHUP, old_sighup); /* restore */
183 signal(SIGTERM, old_sigterm);/* restore */
189 /* enable signalling in kill_child_handler */
194 /* disable signalling in kill_child_handler */
199 yaz_log(YLOG_FATAL, "p1=%d != p=%d", p1, p);
203 if (WIFSIGNALED(status))
205 /* keep the child alive in case of errors, but _log_ */
206 switch(WTERMSIG(status)) {
208 yaz_log(YLOG_WARN, "Received SIGILL from child %ld", (long) p);
212 yaz_log(YLOG_WARN, "Received SIGABRT from child %ld", (long) p);
216 yaz_log(YLOG_WARN, "Received SIGSEGV from child %ld", (long) p);
220 yaz_log(YLOG_WARN, "Received SIGBUS from child %ld", (long) p);
224 yaz_log(YLOG_LOG, "Received SIGTERM from child %ld",
229 yaz_log(YLOG_WARN, "Received SIG %d from child %ld",
230 WTERMSIG(status), (long) p);
234 else if (status == 0)
235 cont = 0; /* child exited normally */
237 { /* child exited with error */
238 yaz_log(YLOG_LOG, "Exit %d from child %ld", status, (long) p);
241 if (cont) /* respawn slower as we get more errors */
251 * indent-tabs-mode: nil
253 * vim: shiftwidth=4 tabstop=8 expandtab