chiark / gitweb /
process: Introduce afterfork()
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Sat, 27 Sep 2014 10:10:06 +0000 (11:10 +0100)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Thu, 2 Oct 2014 15:40:17 +0000 (16:40 +0100)
Rework set_default_signals into afterfork, which does the sigprocmask
too.  This is necessary for processes we fork after
setup_signal_handling(), which otherwise inherit our blocking mask and
non-default handlers.

Call it after each fork() (except the ones we use for daemonising).
As a consequence:
 - hackypar children will die if they get a terminating signal
 - our subprocesses such as `route' and `ifconfig' will inherit
   reasonable signal setups
 - it will be correct to call udp_make_socket during phase RUN
   (previously any authbind would get a strange signal setup)

Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
hackypar.c
process.c
secnet.h
udp.c

index eb445b0847afb68e1139d080e6165571238445e3..abc93c4d982498a8142e1ce95fefd5f9bdd600ce 100644 (file)
@@ -55,6 +55,7 @@ static HPState start(void)
     }
 
     if (!child) { /* we are the child */
+       afterfork();
        return hp_compute;
     }
 
index b75b9c0d6e70159ec60d56738e4e6bfe05a551f7..edc87ac191081f4b64db3e479b848a25be52deea 100644 (file)
--- a/process.c
+++ b/process.c
@@ -35,8 +35,6 @@ static struct signotify *sigs=NULL;
 
 static int spw,spr; /* file descriptors for signal notification pipe */
 
-static void set_default_signals(void);
-
 /* Long-lived subprocesses can only be started once we've started
    signal processing so that we can catch SIGCHLD for them and report
    their exit status using the callback function.  We block SIGCHLD
@@ -58,8 +56,7 @@ pid_t makesubproc(process_entry_fn *entry, process_callback_fn *cb,
     p=fork();
     if (p==0) {
        /* Child process */
-       set_default_signals();
-       sigprocmask(SIG_SETMASK,&emptyset,NULL);
+       afterfork();
        entry(est);
        abort();
     } else if (p==-1) {
@@ -155,6 +152,7 @@ int sys_cmd(const char *path, const char *arg, ...)
           if the execvp() fails this seems somewhat pointless, and
           increases the chance of the child process failing before it
           gets to exec(). */
+       afterfork();
        va_start(ap,arg);
        args[0]=(char *)arg; /* program name */
        i=1;
@@ -214,7 +212,7 @@ static void signal_afterpoll(void *st, struct pollfd *fds, int nfds)
     }
 }
 
-static void set_default_signals(void)
+void afterfork(void)
 {
     struct signotify *n;
     sigset_t done;
@@ -229,6 +227,9 @@ static void set_default_signals(void)
            sa.sa_flags=0;
            sigaction(n->signum,&sa,NULL);
        }
+
+    sigemptyset(&emptyset);
+    sigprocmask(SIG_SETMASK,&emptyset,NULL);
 }
 
 static void signal_handler(int signum)
index 0d0e02edd716dbc07eb759aa4d6365d44b475bb3..dad9fbd04df6bd33c8ad3ffbcdb8178092b9b05e 100644 (file)
--- a/secnet.h
+++ b/secnet.h
@@ -59,6 +59,10 @@ extern struct log_if *system_log;
 /* from process.c */
 extern void start_signal_handling(void);
 
+void afterfork(void);
+/* Must be called before exec in every child made after
+   start_signal_handling.  Safe to call in earlier children too. */
+
 /***** CONFIGURATION support *****/
 
 extern bool_t just_check_config; /* If True then we're going to exit after
diff --git a/udp.c b/udp.c
index b91559d9ff6fadcd79f92334015fdb930fd8f6aa..fb00a5627ebe43e3d2ca9473ce7ffb2de6a18e7c 100644 (file)
--- a/udp.c
+++ b/udp.c
@@ -223,6 +223,7 @@ bool_t udp_make_socket(struct udpcommon *uc, struct udpsock *us,
            char *argv[5], addrstr[33], portstr[5];
            const char *addrfam;
            int port;
+           afterfork();
            switch (addr->sa.sa_family) {
            case AF_INET:
                sprintf(addrstr,"%08lX",(long)addr->sin.sin_addr.s_addr);