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 report its exit status */
147 lg_exitstatus(0,"sys_cmd",0,M_ERR
,rv
,path
);
152 /* Child -> exec command */
153 /* Really we ought to strcpy() the arguments into the args array,
154 since the arguments are const char *. Since we'll exit anyway
155 if the execvp() fails this seems somewhat pointless, and
156 increases the chance of the child process failing before it
159 args
[0]=(char *)arg
; /* program name */
161 while ((args
[i
++]=va_arg(ap
,char *)));
163 fprintf(stderr
, "sys_cmd(%s,%s,...): %s\n", path
, arg
, strerror(errno
));
167 fatal_perror("sys_cmd(%s,%s,...)", path
, arg
);
173 static beforepoll_fn signal_beforepoll
;
174 static int signal_beforepoll(void *st
, struct pollfd
*fds
, int *nfds_io
,
177 BEFOREPOLL_WANT_FDS(1);
179 fds
[0].events
=POLLIN
;
183 /* Bodge to work around Ubuntu's strict header files */
184 static void discard(int anything
) {}
186 static afterpoll_fn signal_afterpoll
;
187 static void signal_afterpoll(void *st
, struct pollfd
*fds
, int nfds
)
193 if (nfds
&& (fds
->revents
& POLLIN
)) {
194 discard(read(spr
,buf
,16));
195 /* We don't actually care what we read; as
196 long as there was at least one byte
197 (which there was) we'll pick up the
198 signals in the pending set */
200 /* We reset 'pending' before processing any of the signals
201 that were pending so that we don't miss any signals that
202 are delivered partway-through processing (all we assume
203 about signal notification routines is that they handle all
204 the work available at their _start_ and only optionally any
205 work that arrives part-way through their execution). */
206 sigprocmask(SIG_SETMASK
,&fullset
,&old
);
208 sigemptyset(&pending
);
209 sigprocmask(SIG_SETMASK
,&old
,NULL
);
211 for (n
=sigs
; n
; n
=n
->next
)
212 if (sigismember(&todo
,n
->signum
))
213 n
->notify(n
->cst
,n
->signum
);
217 static void set_default_signals(void)
224 for (n
=sigs
; n
; n
=n
->next
)
225 if (!sigismember(&done
,n
->signum
)) {
226 sigaddset(&done
,n
->signum
);
227 sa
.sa_handler
=SIG_DFL
;
230 sigaction(n
->signum
,&sa
,NULL
);
234 static void signal_handler(int signum
)
238 sigaddset(&pending
,signum
);
239 /* XXX the write() may set errno, which can make the main program fail.
240 However, signal handlers aren't allowed to modify anything which
241 is not of type sig_atomic_t. The world is broken. */
242 /* I have decided to save and restore errno anyway; on most
243 architectures on which secnet can run modifications to errno
244 will be atomic, and it seems to be the lesser of the two
247 discard(write(spw
,&thing
,1));
248 /* We don't care if this fails (i.e. the pipe
249 is full) because the service routine will
250 spot the pending signal anyway */
254 static void register_signal_handler(struct signotify
*s
)
259 if (!signal_handling
) return;
261 if (sigismember(®istered
,s
->signum
)) return;
262 sigaddset(®istered
,s
->signum
);
264 sa
.sa_handler
=signal_handler
;
267 rv
=sigaction(s
->signum
,&sa
,NULL
);
269 fatal_perror("register_signal_handler: sigaction(%d)",s
->signum
);
273 void request_signal_notification(int signum
, signal_notify_fn
*notify
,
279 s
=safe_malloc(sizeof(*s
),"request_signal_notification");
284 sigprocmask(SIG_SETMASK
,&fullset
,&old
);
286 register_signal_handler(s
);
287 sigprocmask(SIG_SETMASK
,&old
,NULL
);
290 void start_signal_handling(void)
295 sigemptyset(&emptyset
);
296 sigfillset(&fullset
);
297 sigemptyset(®istered
);
298 sigemptyset(&pending
);
303 if (fcntl(spw
, F_SETFL
, fcntl(spw
, F_GETFL
)|O_NONBLOCK
)==-1) {
304 fatal_perror("start_signal_handling: fcntl(O_NONBLOCK)");
307 register_for_poll(NULL
,signal_beforepoll
,signal_afterpoll
,"signal");
308 signal_handling
=True
;
310 /* Register signal handlers for all the signals we're interested in */
311 for (i
=sigs
; i
; i
=i
->next
) {
312 register_signal_handler(i
);
315 request_signal_notification(SIGCHLD
,sigchld_handler
,NULL
);