8 /* Process handling - subprocesses, signals, etc. */
10 static bool_t signal_handling=False;
11 static sigset_t emptyset, fullset;
12 static sigset_t registered,pending;
17 process_callback_fn *cb;
23 static struct child *children=NULL;
27 signal_notify_fn *notify;
29 struct signotify *next;
32 static struct signotify *sigs=NULL;
34 static int spw,spr; /* file descriptors for signal notification pipe */
36 static void set_default_signals(void);
38 /* Long-lived subprocesses can only be started once we've started
39 signal processing so that we can catch SIGCHLD for them and report
40 their exit status using the callback function. We block SIGCHLD
41 until signal processing has begun. */
42 pid_t makesubproc(process_entry_fn *entry, process_callback_fn *cb,
43 void *est, void *cst, string_t desc)
48 c=safe_malloc(sizeof(*c),"makesubproc");
53 if (!signal_handling) {
54 fatal("makesubproc called before signal handling started\n");
59 set_default_signals();
60 sigprocmask(SIG_SETMASK,&emptyset,NULL);
64 fatal_perror("makesubproc (%s): fork",desc);
73 static signal_notify_fn sigchld_handler;
74 static void sigchld_handler(void *st, int signum)
76 struct child *i,*n,**p;
79 process_callback_fn *cb;
84 struct work *w=NULL, *nw;
88 for (i=children; i; i=i->next) {
89 rv=waitpid(i->pid,&status,WNOHANG);
91 fatal_perror("sigchld_handler: waitpid");
96 nw=safe_malloc(sizeof(*nw),"sigchld_handler");
106 /* Remove all the finished tasks from the list of children */
107 for (i=children, p=&children; i; i=n) {
117 /* Notify as appropriate, then free the list */
119 w->cb(w->cst,w->pid,w->status);
126 int sys_cmd(const char *path, char *arg, ...)
135 /* Parent -> wait for child */
140 /* Child -> exec command */
143 while ((args[i++]=va_arg(ap,char *)));
148 fatal_perror("sys_cmd(%s,%s,...)");
155 static beforepoll_fn signal_beforepoll;
156 static int signal_beforepoll(void *st, struct pollfd *fds, int *nfds_io,
157 int *timeout_io, const struct timeval *tv_now,
166 fds[0].events=POLLIN;
170 static afterpoll_fn signal_afterpoll;
171 static void signal_afterpoll(void *st, struct pollfd *fds, int nfds,
172 const struct timeval *tv, uint64_t *now)
178 if (nfds && (fds->revents & POLLIN)) {
179 read(spr,buf,16); /* We don't actually care what we read; as
180 long as there was at least one byte
181 (which there was) we'll pick up the
182 signals in the pending set */
184 /* We reset 'pending' before processing any of the signals
185 that were pending so that we don't miss any signals that
186 are delivered partway-through processing (all we assume
187 about signal notification routines is that they handle all
188 the work available at their _start_ and only optionally any
189 work that arrives part-way through their execution). */
190 sigprocmask(SIG_SETMASK,&fullset,&old);
192 sigemptyset(&pending);
193 sigprocmask(SIG_SETMASK,&old,NULL);
195 for (n=sigs; n; n=n->next)
196 if (sigismember(&todo,n->signum))
197 n->notify(n->cst,n->signum);
201 static void set_default_signals(void)
208 for (n=sigs; n; n=n->next)
209 if (!sigismember(&done,n->signum)) {
210 sigaddset(&done,n->signum);
211 sa.sa_handler=SIG_DFL;
214 sigaction(n->signum,&sa,NULL);
218 static void signal_handler(int signum)
221 sigaddset(&pending,signum);
222 write(spw,&thing,1); /* We don't care if this fails (i.e. the pipe
223 is full) because the service routine will
224 spot the pending signal anyway */
227 static void register_signal_handler(struct signotify *s)
232 if (!signal_handling) return;
234 if (sigismember(®istered,s->signum)) return;
235 sigaddset(®istered,s->signum);
237 sa.sa_handler=signal_handler;
240 rv=sigaction(s->signum,&sa,NULL);
242 fatal_perror("register_signal_handler: sigaction(%d)",s->signum);
246 void request_signal_notification(int signum, signal_notify_fn *notify,
252 s=safe_malloc(sizeof(*s),"request_signal_notification");
257 sigprocmask(SIG_SETMASK,&fullset,&old);
259 register_signal_handler(s);
260 sigprocmask(SIG_SETMASK,&old,NULL);
263 void start_signal_handling(void)
268 sigemptyset(&emptyset);
269 sigfillset(&fullset);
270 sigemptyset(®istered);
271 sigemptyset(&pending);
274 fatal_perror("start_signal_handling: pipe");
278 if (fcntl(spw, F_SETFL, fcntl(spw, F_GETFL)|O_NONBLOCK)==-1) {
279 fatal_perror("start_signal_handling: fcntl(O_NONBLOCK)");
282 register_for_poll(NULL,signal_beforepoll,signal_afterpoll,1,"signal");
283 signal_handling=True;
285 /* Register signal handlers for all the signals we're interested in */
286 for (i=sigs; i; i=i->next) {
287 register_signal_handler(i);
290 request_signal_notification(SIGCHLD,sigchld_handler,NULL);