chiark / gitweb /
prefork-interp: diagrams
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Sat, 20 Aug 2022 15:05:12 +0000 (16:05 +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

index 105f21c5761edd66c5ea67c9dd7c9aab9d561d0d..2e7f42e5d7706ac325eccca431f530b4ba8a883a 100644 (file)
  */
 
 /*
-                                   
-                                                 
-                                                 
+***************************************************************************
+\f
   State during service execution, process parentage and key fds
 
-    ---- pipes, sockets   
-    012  descriptors      
-    -==- fds shared       
-    ||   process parentage
-    &&   session leader (daemon) 
-    &    process group leader    
-                             
-      CALLER                 
-        ||                   
-        ||                   
+    ----      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) 
+        ||       call                 (accept) \     ,------2
+        || ,-----------------------------.     SERVER -----0 WATCHER(C)
       CLIENT 2--=fdpassed>=---------.     \      || &&          |      &&
-       (C)  1--=fdpassed>=---------. \     \     ||           inotify    
-           0--=fdpassed>=---------. \ \     \    ||           sockpath   
-                                   \ \ \     \   ||                      
-                                   | | |\     |  || 
-                                   | | | \    |  || 
+       (C)  1--=fdpassed>=---------. \     \     ||           inotify
+           0--=fdpassed>=---------. \ \     \    ||           sockpath
+                                   \ \ \     \   ||
+                                   | | |\     |  ||
+                                   | | | \    |  ||
                                    | \ |  \   \  ||
                                     \ \ \  \   MONITOR &
-                                     \ \ \  `12  ||  |  
-                                      \ \ \      ||  |  
+                                     \ \ \  `12  ||  |
+                                      \ \ \      ||  |
                                        \ \ \     ||  |execterm
-                                        \ \ \    ||  |  
-                                         \ \ \   ||  |  
-                                          \ \ 2  ||  |  
-                                           \ 1 EXECUTOR 
-                                            0           
-                                                        
- Control flow and causality                             
-                                                        
-    | - \ /    process control flow                     
-    ...        causes mediated by fds or other IPC etc. 
+                                        \ \ \    ||  |
+                                         \ \ \   ||  |
+                                          \ \ 2  ||  |
+                                           \ 1 EXECUTOR
+                                            0
+
+***************************************************************************
+\f
+ 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)                               
-         |                                   
+    #          language/implementation boundary
+    *1         line continued elsewhere
+    event?     condition
+    ______     process termination (after reaping, if shown)
+
+
+      CALLER
+         |
+         |fork/exec
+         |
+      CLIENT
+         |
       attempt to connect, and read greeting
-         |failure?                \success?  
-         |                         \         
-      tidy up stale /run entries    continue from send_fds, below  
-      acquire lock                                                 
-         |                                                         
-      retry attempt to connect, and read greeting                  
-         |failure?                \success?                        
-         |                         \                               
-      create listening socket     release lock                     
-         |                           \                             
-      fork/daemonise                  continue from send_fds, below                    
-         |    `------------------.           
+         |failure?                \success?
+         |                         \
+      tidy up stale /run entries    *1 (continue from send_fds, below)
+      acquire lock
+         |
+      retry attempt to connect, and read greeting
+         |failure?                \success?
+         |                         \
+      create listening socket     release lock
+         |                           \
+      fork/daemonise                  *1
+         |    `------------------.
          |                      WATCHER(C) &&
-         |                                  
-       make "fake" initial call socketpair                       
-         |                                           C prefork-interp               
-       fork/exec  + + + + + + + + + + + + + + + + + + + + + + + + + + + +           
-         |      `------.                             Perl, application              
-         |      +    SCRIPT (setup)                                                 
-         |      +      |                                                            
-         |      +   script initialisation                                           
-         |      +      |                             Perl, application                     
-         |      + + + +| + + + + + + + + + + + + + + + + + + + + + + + +                   
-         |      +      |                             Perl, prefork-interp                      
-         |      +   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  | |   
-         |      +   setpgrpt &                       | | |   
-         |      +      |                             | | |   
-         |      + send greeting                      | | |   
-      read greeting    |                             exit    
-         |      +      |                                     
-      release lock     |          from read greeting success, above 
-         |    ________ | ________/                       
-         |   /  +      |                                     
-      send fds....     |                                     
-         |      + receive fds                                
-         |      +         |                                  
-         |      +     fork for executor                      
-         |      +   p  |parent        \child         Perl, prefork-interp                                         
-         |      +      |        + + + + \+ + + + + + + + + + + + + + + +                            
-         |      +      |        +   execute service  Perl, application                                 
-         |      +      |        +       |                               
-         |      +wait for read  +       |                               
-         |      +  (select)     +       |                               
-         |      +    |   |      +       |                               
-         |      +        |      +     exits                             
-         |      +        |      +     kernel closes execterm            
-         |      +        | ,.........../|                               
-         |      +  execterm?    +       |                               
-         |      +        |      +     zombie                            
-         |      +        | ,........../             
-         |      +   waitpid     +
-         |      +        |      +                                         
-         |    ,..,..send status +
-    read 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
- *                              (including reading ack byte)
- *                            if fails or garbage
- *                            === acquires lock ===
- *                            makes new listening socket
- *                            makes watcher pipes
- *                            forks watcher and awaits
- *                            makes first-instance socketpair
- *                            forks setup (script, sock fds indicated in env)
- *                            fd0, fd1, fd2: from-outer
- *                            other fd: call(client-end)(fake)
- *                            reaps setup (and reports error)
- *                            (implicitly releases lock)
- *
- *     watcher                fd[012]: watcher pipes
- *                            starts watch on socket path
- *                            sets stderr to line buffered
- *                            sets stdin to nonblocking
- *                            daemonises (one fork, becomes session leader)
- *                            when socket stat changes, quit
- *
- *     setup (pre-exec)       fd0: null,
- *                            fd[12]: fd2-from-outer
- *                            env fds: listener, call(server-end)(fake),
- *                                      watcher read, watcher write
- *                            close fd: lockfile
- *                            possibly clean env, argv
- *
- *     setup (script)         runs initialisation parts of the script
- *                            at prefork establishment point:
- *     setup (pm) [1]         opens syslog
- *                            forks for server
- *                [2]         exits
- *
- *        server (pm) [1]     [fd0: null],
- *                            [fd[12]: fd2-from-outer]
- *                            setsid
- *                            right away, forks init monitor
- *                    [2]     closes outer caller fds and call(fake)
- *        [server (pm)]       fd[012]: null
- *                            other fds: listener, syslog
- *                            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
- *                               sends fds
- *
- *        [server (script)]   accepts, forks subseq monitor
- *
- *          monitor [1]       [fd0: null]
- *           (init            [fd[12]: init: fd2-from-outer; subseq: null]
- *             or             errors: init: fd2; subseq: syslog
- *            subseq)         other fds: syslog, call(server-end)
- *                            sends ack byte
- *                            receives args, env, fds
- *                            forks executor
- *
- *            executor        sorts out fds:
- *                            fd0, fd1, fd2: from-outer
- *                            close fds: call(server-end)
- *                            retained fds: syslog
- *
- *                            sets cmdline, env
- *                            runs main part of script
- *                            exits normally
- *
- *          [monitor]         [fd[012]: null]
- *                            [fd[12]: init: fd2-from-outer; subseq: null]
- *                            [errors: init: fd2; subseq: syslog]
- *                            reaps executor
- *                            reports status via socket
- *
- *    [client (C wrapper)]    [fd0, fd1, fd2: from-outer]
- *                            [other fd: call(client-end)]
- *                            receives status, exits appropriately
- *                            (if was bad signal, reports to stderr, exits 127)
- */
+         |
+       make "fake" initial call socketpair                               (C)
+         |                                                    prefork-interp
+       fork/exec   #########################################################
+         |      `-------------.                                  application
+         |         #        SCRIPT (setup)
+         |         #          |
+         |         #       script initialisation
+         |         #          |                                  application
+         |         #  ########|#############################################
+         |         #          |                               prefork-interp
+         |         #       identify fds from envirnment               (Perl)
+         |         #       open syslog
+         |         #          |
+         |         #       dzemonize
+         |   ,.....<....../   |
+      waitpid      #        fork for initial service
+         |         #          |child?       |parent?
+         |         #          |             |
+         |         #          |         SCRIPT [server] &&
+         |         #          |             |
+         |         #          |         ** accept / event loop **
+         |         #          |        accepted?    \      \ \
+         |         #          |            /         \ watch\ \idle
+         |         #          |        fork child     \stderr\ \timeout?
+         |         #          | _________/            |       | |
+         |         #          |/                      |read?  | |
+         |         #     SCRIPT [monitor]             |   eof?| |
+         |         #       setpgrpt &                 |       | |
+         |         #          |                     log msg   | |
+       read   ,....<.....send greeting                |       | |
+      greeting     #          |                    ___________________
+         |         #          |
+      release      #          |
+      lock    *1   #          |
+         |   /     #          |
+      send fds.....>....      |
+         |         #    \receive fds
+         |         #             |
+         |         #         fork for executor                        (Perl)
+         |         #          |parent?        \child?         prefork-interp
+         |         #          |          ######\############################
+         |         #          |          #  SCRIPT (executor)    application
+         |         #          |          #  execute service
+         |         #    wait for read    #       |
+         |         #      (select)       #   terminates
+         |         #        |   |        #       |
+         |         #            |        #    kernel closes execterm
+         |         #            | ,......<....../|
+         |         #      execterm?      #       |
+         |         #            |        #     zombie
+         |         #        |   | ,......<...../
+         |         #       waitpid       #  _______________
+         |         #          |          #
+         |    ,....<....,..send status   #
+    read status    #  ________________   #
+   _____________   #
+
+
+  ********** Or, if client is killed **********
+
+         |         #          |          #  execute service
+     terminates    #    wait for read    #       |
+         |         #      (select)       #       |
+      kernel       #        |   |        #       |
+     closes call   #        |            #       |
+                \..>......_ |            #       |
+   _____________   #       \|call?       #       |
+                   #        |            #       |
+                   #  kill whole pgrp... #    killled
+                   #        |            #     zombie
+                   #        |   | ,......<....../
+                   #       waitpid       #  _______________
+                   #          |          #
+                   #   send exit status  #
+                   #  _____SIGPIPE______ #
+
+***************************************************************************
+\f
+  Sequence of events and fd pluming.
+  NB INCOMPLETE - does not cover execterm, cleanup
+   client (C wrapper)        connects to server
+                               (including reading ack byte)
+                             if fails or garbage
+                             === acquires lock ===
+                             makes new listening socket
+                             makes watcher pipes
+                             forks watcher and awaits
+                             makes first-instance socketpair
+                             forks setup (script, sock fds indicated in env)
+                             fd0, fd1, fd2: from-outer
+                             other fd: call(client-end)(fake)
+                             reaps setup (and reports error)
+                             (implicitly releases lock)
+      watcher                fd[012]: watcher pipes
+                             starts watch on socket path
+                             sets stderr to line buffered
+                             sets stdin to nonblocking
+                             daemonises (one fork, becomes session leader)
+                             when socket stat changes, quit
+      setup (pre-exec)       fd0: null,
+                             fd[12]: fd2-from-outer
+                             env fds: listener, call(server-end)(fake),
+                                       watcher read, watcher write
+                             close fd: lockfile
+                             possibly clean env, argv
+      setup (script)         runs initialisation parts of the script
+                             at prefork establishment point:
+      setup (pm) [1]         opens syslog
+                             forks for server
+                 [2]         exits
+         server (pm) [1]     [fd0: null],
+                             [fd[12]: fd2-from-outer]
+                             setsid
+                             right away, forks init monitor
+                     [2]     closes outer caller fds and call(fake)
+         [server (pm)]       fd[012]: null
+                             other fds: listener, syslog
+                             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
+                                sends fds
+         [server (script)]   accepts, forks subseq monitor
+           monitor [1]       [fd0: null]
+            (init            [fd[12]: init: fd2-from-outer; subseq: null]
+              or             errors: init: fd2; subseq: syslog
+             subseq)         other fds: syslog, call(server-end)
+                             sends ack byte
+                             receives args, env, fds
+                             forks executor
+             executor        sorts out fds:
+                             fd0, fd1, fd2: from-outer
+                             close fds: call(server-end)
+                             retained fds: syslog
+                             sets cmdline, env
+                             runs main part of script
+                             exits normally
+           [monitor]         [fd[012]: null]
+                             [fd[12]: init: fd2-from-outer; subseq: null]
+                             [errors: init: fd2; subseq: syslog]
+                             reaps executor
+                             reports status via socket
+     [client (C wrapper)]    [fd0, fd1, fd2: from-outer]
+                             [other fd: call(client-end)]
+                             receives status, exits appropriately
+                             (if was bad signal, reports to stderr, exits 127)
+
+***************************************************************************
+\f
+*/
 
 #include <arpa/inet.h>