10 /* Process handling - subprocesses, signals, etc. */
12 static bool_t signal_handling=False;
13 static sigset_t emptyset, fullset;
14 static sigset_t registered,pending;
19 process_callback_fn *cb;
25 static struct child *children=NULL;
29 signal_notify_fn *notify;
31 struct signotify *next;
34 static struct signotify *sigs=NULL;
36 static int spw,spr; /* file descriptors for signal notification pipe */
38 static void set_default_signals(void);
40 /* Long-lived subprocesses can only be started once we've started
41 signal processing so that we can catch SIGCHLD for them and report
42 their exit status using the callback function. We block SIGCHLD
43 until signal processing has begun. */
44 pid_t makesubproc(process_entry_fn *entry, process_callback_fn *cb,
45 void *est, void *cst, cstring_t desc)
50 c=safe_malloc(sizeof(*c),"makesubproc");
55 if (!signal_handling) {
56 fatal("makesubproc called before signal handling started");
61 set_default_signals();
62 sigprocmask(SIG_SETMASK,&emptyset,NULL);
66 fatal_perror("makesubproc (%s): fork",desc);
75 static signal_notify_fn sigchld_handler;
76 static void sigchld_handler(void *st, int signum)
78 struct child *i,*n,**p;
81 process_callback_fn *cb;
86 struct work *w=NULL, *nw;
90 for (i=children; i; i=i->next) {
91 rv=waitpid(i->pid,&status,WNOHANG);
93 fatal_perror("sigchld_handler: waitpid");
98 nw=safe_malloc(sizeof(*nw),"sigchld_handler");
108 /* Remove all the finished tasks from the list of children */
109 for (i=children, p=&children; i; i=n) {
119 /* Notify as appropriate, then free the list */
121 w->cb(w->cst,w->pid,w->status);
128 int sys_cmd(const char *path, const char *arg, ...)
136 /* Parent -> wait for child */
138 rc = waitpid(c,&rv,0);
139 } while(rc < 0 && errno == EINTR);
141 fatal_perror("sys_cmd: waitpid for %s", path);
142 if (rc != c) /* OS has gone mad */
143 fatal("sys_cmd: waitpid for %s returned wrong process ID!",
146 /* If the command failed reporting its exit status */
148 Message(M_ERR, "sys_cmd(%s,%s,...) exited with status %d\n",
149 path, arg, WEXITSTATUS(rv));
150 else if(WIFSIGNALED(rv))
151 Message(M_ERR, "sys_cmd(%s,%s,...) exited with signal %d (%s)%s\n",
152 path, arg, WTERMSIG(rv), strsignal(WTERMSIG(rv)),
153 WCOREDUMP(rv) ? " - core dumped" : "");
155 Message(M_ERR, "sys_cmd(%s,%s,...) exited with wstat %#x",
161 /* Child -> exec command */
162 /* Really we ought to strcpy() the arguments into the args array,
163 since the arguments are const char *. Since we'll exit anyway
164 if the execvp() fails this seems somewhat pointless, and
165 increases the chance of the child process failing before it
168 args[0]=(char *)arg; /* program name */
170 while ((args[i++]=va_arg(ap,char *)));
172 fprintf(stderr, "sys_cmd(%s,%s,...): %s\n", path, arg, strerror(errno));
176 fatal_perror("sys_cmd(%s,%s,...)", path, arg);
182 static beforepoll_fn signal_beforepoll;
183 static int signal_beforepoll(void *st, struct pollfd *fds, int *nfds_io,
192 fds[0].events=POLLIN;
196 static afterpoll_fn signal_afterpoll;
197 static void signal_afterpoll(void *st, struct pollfd *fds, int nfds)
203 if (nfds && (fds->revents & POLLIN)) {
204 read(spr,buf,16); /* We don't actually care what we read; as
205 long as there was at least one byte
206 (which there was) we'll pick up the
207 signals in the pending set */
209 /* We reset 'pending' before processing any of the signals
210 that were pending so that we don't miss any signals that
211 are delivered partway-through processing (all we assume
212 about signal notification routines is that they handle all
213 the work available at their _start_ and only optionally any
214 work that arrives part-way through their execution). */
215 sigprocmask(SIG_SETMASK,&fullset,&old);
217 sigemptyset(&pending);
218 sigprocmask(SIG_SETMASK,&old,NULL);
220 for (n=sigs; n; n=n->next)
221 if (sigismember(&todo,n->signum))
222 n->notify(n->cst,n->signum);
226 static void set_default_signals(void)
233 for (n=sigs; n; n=n->next)
234 if (!sigismember(&done,n->signum)) {
235 sigaddset(&done,n->signum);
236 sa.sa_handler=SIG_DFL;
239 sigaction(n->signum,&sa,NULL);
243 static void signal_handler(int signum)
247 sigaddset(&pending,signum);
248 /* XXX the write() may set errno, which can make the main program fail.
249 However, signal handlers aren't allowed to modify anything which
250 is not of type sig_atomic_t. The world is broken. */
251 /* I have decided to save and restore errno anyway; on most
252 architectures on which secnet can run modifications to errno
253 will be atomic, and it seems to be the lesser of the two
256 write(spw,&thing,1); /* We don't care if this fails (i.e. the pipe
257 is full) because the service routine will
258 spot the pending signal anyway */
262 static void register_signal_handler(struct signotify *s)
267 if (!signal_handling) return;
269 if (sigismember(®istered,s->signum)) return;
270 sigaddset(®istered,s->signum);
272 sa.sa_handler=signal_handler;
275 rv=sigaction(s->signum,&sa,NULL);
277 fatal_perror("register_signal_handler: sigaction(%d)",s->signum);
281 void request_signal_notification(int signum, signal_notify_fn *notify,
287 s=safe_malloc(sizeof(*s),"request_signal_notification");
292 sigprocmask(SIG_SETMASK,&fullset,&old);
294 register_signal_handler(s);
295 sigprocmask(SIG_SETMASK,&old,NULL);
298 void start_signal_handling(void)
303 sigemptyset(&emptyset);
304 sigfillset(&fullset);
305 sigemptyset(®istered);
306 sigemptyset(&pending);
309 fatal_perror("start_signal_handling: pipe");
313 if (fcntl(spw, F_SETFL, fcntl(spw, F_GETFL)|O_NONBLOCK)==-1) {
314 fatal_perror("start_signal_handling: fcntl(O_NONBLOCK)");
317 register_for_poll(NULL,signal_beforepoll,signal_afterpoll,1,"signal");
318 signal_handling=True;
320 /* Register signal handlers for all the signals we're interested in */
321 for (i=sigs; i; i=i->next) {
322 register_signal_handler(i);
325 request_signal_notification(SIGCHLD,sigchld_handler,NULL);