chiark / gitweb /
prefork-interp: diagrams
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Sat, 20 Aug 2022 13:23:58 +0000 (14:23 +0100)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Sun, 21 Aug 2022 20:21:10 +0000 (21:21 +0100)
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
cprogs/prefork-interp.c
perl/Prefork.pm

index b59eed8204cd367d52e6bd98d70f44404554fb3f..f0bc785859743acd3a2d4267e4c777e995a0a3c5 100644 (file)
  *         ident covers only env vars specified  with -E
  *         ident covers only arguments interpreter and (if present) script
  */
+
+/*
+                                   
+                                                 
+                                                 
+  State during service execution, process parentage and key fds
+
+    ---- pipes, sockets   
+    012  descriptors      
+    -==- fds shared       
+    ||   process parentage
+    &&   session leader (daemon) 
+    &    process group leader    
+                             
+      CALLER                 
+        ||                   
+        ||                   
+        ||                               listen     watch-err/in
+        ||       call                 (accept) \     ,------2          
+        || ,-----------------------------.     SERVER -----0 WATCHER(C) 
+      CLIENT 2--=fdpassed>=---------.     \      || &&          |      &&
+       (C)  1--=fdpassed>=---------. \     \     ||           inotify    
+           0--=fdpassed>=---------. \ \     \    ||           sockpath   
+                                   \ \ \     \   ||                      
+                                   | | |\     |  || 
+                                   | | | \    |  || 
+                                   | \ |  \   \  ||
+                                    \ \ \  \   MONITOR &
+                                     \ \ \  `12  ||  |  
+                                      \ \ \      ||  |  
+                                       \ \ \     ||  |execterm
+                                        \ \ \    ||  |  
+                                         \ \ \   ||  |  
+                                          \ \ 2  ||  |  
+                                           \ 1 EXECUTOR 
+                                            0           
+                                                        
+ Control flow and causality                             
+                                                        
+    | - \ /    process control flow                     
+    ...        causes mediated by fds or other IPC etc. 
+    &&         session leader (daemon)
+    &          process group leader
+                                             
+     CALLER                                  
+         |                                   
+         |fork/exec                          
+         |                                   
+     CLIENT(C)                               
+      tidy up stale sockets etc.             
+      acquire lock                           
+      create listening socket                
+         |                                   
+      fork/daemonise                         
+         |    `------------------.           
+         |                      WATCHER(C) &&
+         |                                  
+       make "fake" initial call socketpair  
+         |                                  
+       fork/exec                            
+         |      `------.                    
+         |           SCRIPT (setup)         
+         |             |                    
+         |          script initialisation   
+         |             |                    
+         |          identify fds from envirnment
+         |          open syslog                 
+         |             |                           
+         |          dzemonize
+         |   ,...../   |                           
+      waitpid          |                           
+         |           fork for initial service            
+         |             |child        |parent                 
+         |             |             |                       
+         |             |         SCRIPT [server] &&
+         |             |             |                       
+         |             |         ** accept / event loop **   
+         |             |            /            \ \ \                   
+         |             |        accepted?         \ \ \idle timeout?     
+         |             |           |               \ \ \                 
+         |             |        fork child          \ \ \                
+         |             | _________/            watch | |watch stderr eof?
+         |             |/                      stderr| | |          
+         |        SCRIPT [monitor]                   | | |   
+         |             |                      log msg  | |   
+         |        send greeting                      | | |   
+      read greeting    |                             | | |   
+         |             |                             exit    
+      release lock     |                                     
+         |             |                                     
+      send fds....     |                                     
+         |        receive fds                                
+         |             |                                     
+         |         fork for executor                         
+         |             |       \                             
+         |             |        \child
+         |             |         \                       
+         |             |        setpgrp &                
+         |             |        execute service          
+         |             |            |                    
+         |       wait for read      |    
+         |         (select)         |    
+         |           |   |          |          
+         |               |        exits  
+         |               |        kernel closes execterm
+         |               | ,......./|                   
+         |         execterm?        |    
+         |               |        zombie 
+         |               | ,....../      
+         |          waitpid              
+         |               |               
+         |          send exit status     
+      read exit status                   
+                                         
+                                         
+  Or, if client is killed                
+                                         
+         |             |            |          
+         |       wait for read      |    
+         |         (select)         |    
+         |           |   |          |          
+       exits         |              |    
+         |           |              |    
+     kernel closes   |              |    
+                \....|              |    
+                     call?          |    
+                     |              |    
+               kill whole pgrp...   |    
+                         |       killled
+                         |        zombie
+                         | ,....../
+                    waitpid
+                         |  
+                    send exit status
+                    die due to SIGPIPE
+         
+                
+ */                 
 /*
  * Process structure:
  *  client (C wrapper)        connects to server
  *                            runs in loop accepting and forking,
  *                            reaping and limiting children (incl init monitor)
  *                            reports failures of monitors to syslog
- *                            
+ *
  *  [client (C wrapper)]      if client connect succeeds:
  *                            now fd: call(client-end)
  *                               sends message with: cmdline, env
@@ -156,7 +294,7 @@ static void propagate_exit_status(int status, const char *what) {
       r = sigaction(sig, &sa, 0);
       if (r) diee("failed to reset signal handler while propagating %s",
                  signame);
-      
+
       sigset_t sset;
       sigemptyset(&sset);
       sigaddset(&sset, sig);
@@ -297,7 +435,7 @@ static void prepare_data(size_t *len, char **buf,
     *buf += dl;
   }
 }
-  
+
 static void prepare_length(size_t *len, char **buf, size_t dl_sz) {
   if (dl_sz > UINT32_MAX) die_data_overflow();
   uint32_t dl = htonl(dl_sz);
@@ -475,7 +613,7 @@ static FILE *connect_existing(void) {
 static void watcher_cb_stdin(uv_poll_t *handle, int status, int events) {
   char c;
   int r;
-  
+
   if ((errno = -status)) diee("watcher: poll stdin");
   for (;;) {
     r= read(0, &c, 1);
@@ -685,7 +823,7 @@ static void make_executor_argv(const char *const *argv) {
 
   EACH_NEW_ARG( *out++ = arg; );
   *out++ = 0;
-}  
+}
 
 int main(int argc_unused, const char *const *argv) {
   process_opts(&argv);
index f70edd451dfddad805d601ae1407b366aa8b17e4..2ee8e57e3d5fbb2a658b505bf82c8e51888100e7 100644 (file)
@@ -9,7 +9,7 @@ use strict;
 use Carp;
 use Fcntl qw(F_GETFL F_SETFL O_NONBLOCK);
 use IO::FDPass;
-use POSIX qw(_exit setsid :sys_wait_h :errno_h);
+use POSIX qw(_exit setsid :sys_wait_h :errno_h :signal_h);
 use Sys::Syslog qw(openlog syslog LOG_INFO LOG_ERR LOG_WARNING);
 
 our $logger;
@@ -224,7 +224,7 @@ sub initialisation_complete {
       my $got = waitpid -1, ($full ? 0 : WNOHANG);
       $got >= 0 or fail_log("failed to wait for monitor(s): $!");
       if ($got) {
-       if ($?) {
+       if ($? && $? != SIGPIPE) {
          syslog(LOG_WARNING,
  "$0 prefork [$$]: monitor process [$got] failed with wait status $?");
        }