polypath: Break up child process handling
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Tue, 30 Sep 2014 17:33:59 +0000 (18:33 +0100)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Tue, 21 Oct 2014 00:07:11 +0000 (01:07 +0100)
This will allow us to have different child processes, and also reuse
much of the same child output processing code in a different context.

No functional change (other than a tiny change to a message).

Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
polypath.c

index ddcfeeb..770ffc2 100644 (file)
@@ -367,22 +367,10 @@ static void polypath_record_ifaddr(struct polypath *st,
     dump_pria(st,0);
 }
 
-static void polypath_afterpoll(void *state, struct pollfd *fds, int nfds)
+static void subproc_problem(struct polypath *st,
+                           enum async_linebuf_result alr, const char *emsg)
 {
-    struct polypath *st=state;
-    enum async_linebuf_result alr;
-    const char *emsg;
     int status;
-
-    if (nfds<1) return;
-
-    while ((alr=async_linebuf_read(fds,&st->lbuf,&emsg)) == async_linebuf_ok)
-       polypath_process_monitor_line(st,st->lbuf.base,
-                                     polypath_record_ifaddr);
-
-    if (alr==async_linebuf_nothing)
-       return;
-
     assert(st->monitor_pid);
 
     pid_t gotpid=waitpid(st->monitor_pid,&status,WNOHANG);
@@ -398,10 +386,32 @@ static void polypath_afterpoll(void *state, struct pollfd *fds, int nfds)
        lg_perror(LG,M_FATAL,0,"unexpected EOF from interface monitor");
     else
        lg_perror(LG,M_FATAL,0,"bad output from interface monitor: %s",emsg);
-
     assert(!"not reached");
 }
 
+static void afterpoll_monitor(struct polypath *st, struct pollfd *fd,
+                             polypath_ppml_callback_type *callback)
+{
+    enum async_linebuf_result alr;
+    const char *emsg;
+    
+    while ((alr=async_linebuf_read(fd,&st->lbuf,&emsg)) == async_linebuf_ok)
+       polypath_process_monitor_line(st,st->lbuf.base,callback);
+
+    if (alr==async_linebuf_nothing)
+       return;
+
+    subproc_problem(st,alr,emsg);
+}
+
+static void polypath_afterpoll_monitor(void *state, struct pollfd *fds,
+                                      int nfds)
+{
+    struct polypath *st=state;
+    if (nfds<1) return;
+    afterpoll_monitor(st,fds,polypath_record_ifaddr);
+}
+
 /* Actual udp packet sending work */
 static bool_t polypath_sendmsg(void *commst, struct buffer_if *buf,
                          const struct comm_addr *dest)
@@ -443,35 +453,47 @@ static bool_t polypath_sendmsg(void *commst, struct buffer_if *buf,
     return allreasonable;
 }
 
-static void polypath_phase_startmonitor(void *sst, uint32_t newphase)
+static void child_monitor(struct polypath *st, int childfd)
+{
+    dup2(childfd,1);
+    execvp(st->monitor_command[0],(char**)st->monitor_command);
+    fprintf(stderr,"secnet: cannot execute %s: %s\n",
+           st->monitor_command[0], strerror(errno));
+    exit(-1);
+}
+
+static void start_subproc(struct polypath *st, void (*make_fdpair)(int[2]),
+                         void (*child)(struct polypath *st, int childfd))
 {
-    struct polypath *st=sst;
     int pfds[2];
 
     assert(!st->monitor_pid);
     assert(st->monitor_fd<0);
 
-    pipe_cloexec(pfds);
+    make_fdpair(pfds);
 
     pid_t pid=fork();
     if (!pid) {
        afterfork();
-       dup2(pfds[1],1);
-       execvp(st->monitor_command[0],(char**)st->monitor_command);
-       fprintf(stderr,"secnet: cannot execute %s: %s\n",
-               st->monitor_command[0], strerror(errno));
-       exit(-1);
+       child(st,pfds[1]);
+       abort();
     }
     if (pid<0)
-       fatal_perror("%s: failed to fork for interface monitor",
+       fatal_perror("%s: failed to fork for interface monitoring",
                     st->uc.cc.cl.description);
 
     close(pfds[1]);
     st->monitor_pid=pid;
     st->monitor_fd=pfds[0];
     setnonblock(st->monitor_fd);
+}
 
-    register_for_poll(st,polypath_beforepoll,polypath_afterpoll,"polypath");
+static void polypath_phase_startmonitor(void *sst, uint32_t newphase)
+{
+    struct polypath *st=sst;
+    start_subproc(st,pipe_cloexec,child_monitor);
+    register_for_poll(st,polypath_beforepoll,
+                     polypath_afterpoll_monitor,"polypath");
 }
 
 static void polypath_phase_shutdown(void *sst, uint32_t newphase)