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 extern void makesubproc(process_entry_fn *entry, process_callback_fn *cb,
43 void *est, void *cst, string_t desc)
49 c=safe_malloc(sizeof(*c),"makesubproc");
54 if (!signal_handling) {
55 sigemptyset(&sigchld);
56 sigaddset(&sigchld,SIGCHLD);
57 sigprocmask(SIG_BLOCK,&sigchld,NULL);
62 set_default_signals();
63 sigprocmask(SIG_SETMASK,&emptyset,NULL);
67 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, char *arg, ...)
137 /* Parent -> wait for child */
142 /* Child -> exec command */
145 while ((args[i++]=va_arg(ap,char *)));
150 fatal_perror("sys_cmd(%s,%s,...)");
157 static beforepoll_fn signal_beforepoll;
158 static int signal_beforepoll(void *st, struct pollfd *fds, int *nfds_io,
159 int *timeout_io, const struct timeval *tv_now,
168 fds[0].events=POLLIN;
172 static afterpoll_fn signal_afterpoll;
173 static void signal_afterpoll(void *st, struct pollfd *fds, int nfds,
174 const struct timeval *tv, uint64_t *now)
180 if (nfds && (fds->revents & POLLIN)) {
181 read(spr,buf,16); /* We don't actually care what we read; as
182 long as there was at least one byte
183 (which there was) we'll pick up the
184 signals in the pending set */
186 /* We reset 'pending' before processing any of the signals
187 that were pending so that we don't miss any signals that
188 are delivered partway-through processing (all we assume
189 about signal notification routines is that they handle all
190 the work available at their _start_ and only optionally any
191 work that arrives part-way through their execution). */
192 sigprocmask(SIG_SETMASK,&fullset,&old);
194 sigemptyset(&pending);
195 sigprocmask(SIG_SETMASK,&old,NULL);
197 for (n=sigs; n; n=n->next)
198 if (sigismember(&todo,n->signum))
199 n->notify(n->cst,n->signum);
203 static void set_default_signals(void)
210 for (n=sigs; n; n=n->next)
211 if (!sigismember(&done,n->signum)) {
212 sigaddset(&done,n->signum);
213 sa.sa_handler=SIG_DFL;
216 sigaction(n->signum,&sa,NULL);
220 static void signal_handler(int signum)
223 sigaddset(&pending,signum);
224 write(spw,&thing,1); /* We don't care if this fails (i.e. the pipe
225 is full) because the service routine will
226 spot the pending signal anyway */
229 static void register_signal_handler(struct signotify *s)
234 if (!signal_handling) return;
236 if (sigismember(®istered,s->signum)) return;
237 sigaddset(®istered,s->signum);
239 sa.sa_handler=signal_handler;
242 rv=sigaction(s->signum,&sa,NULL);
244 fatal_perror("register_signal_handler: sigaction(%d)",s->signum);
248 void request_signal_notification(int signum, signal_notify_fn *notify,
254 s=safe_malloc(sizeof(*s),"request_signal_notification");
259 sigprocmask(SIG_SETMASK,&fullset,&old);
261 register_signal_handler(s);
262 sigprocmask(SIG_SETMASK,&old,NULL);
265 void start_signal_handling(void)
270 sigemptyset(&emptyset);
271 sigfillset(&fullset);
272 sigemptyset(®istered);
273 sigemptyset(&pending);
276 fatal_perror("start_signal_handling: pipe");
280 if (fcntl(spw, F_SETFL, fcntl(spw, F_GETFL)|O_NONBLOCK)==-1) {
281 fatal_perror("start_signal_handling: fcntl(O_NONBLOCK)");
284 register_for_poll(NULL,signal_beforepoll,signal_afterpoll,1,"signal");
285 signal_handling=True;
287 /* Register signal handlers for all the signals we're interested in */
288 for (i=sigs; i; i=i->next) {
289 register_signal_handler(i);
292 request_signal_notification(SIGCHLD,sigchld_handler,NULL);