URI: 
       tadd RFNOWAIT.  this was probably a bad idea. - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
   DIR commit 06c4fd06cae9dd155eb284eac046f54d1c75bb24
   DIR parent ee6d04f9feec5011da240a9e08704c775806c331
  HTML Author: rsc <devnull@localhost>
       Date:   Wed, 21 Apr 2004 22:44:37 +0000
       
       add RFNOWAIT.  this was probably a bad idea.
       
       Diffstat:
         M src/lib9/mkfile                     |       1 +
         M src/lib9/rfork.c                    |      67 +++++++++++++++++++++++++++++--
       
       2 files changed, 65 insertions(+), 3 deletions(-)
       ---
   DIR diff --git a/src/lib9/mkfile b/src/lib9/mkfile
       t@@ -118,6 +118,7 @@ LIB9OFILES=\
                mallocz.$O\
                nan.$O\
                needsrcquote.$O\
       +        needstack.$O\
                netmkaddr.$O\
                notify.$O\
                nrand.$O\
   DIR diff --git a/src/lib9/rfork.c b/src/lib9/rfork.c
       t@@ -1,4 +1,6 @@
        #include <u.h>
       +#include <sys/wait.h>
       +#include <signal.h>
        #include <libc.h>
        #include "9proc.h"
        #undef rfork
       t@@ -6,16 +8,71 @@
        int
        p9rfork(int flags)
        {
       -        int pid;
       +        int pid, status;
       +        int p[2];
       +        int n;
       +        char buf[128], *q;
        
       +        _p9uproc(0);
                if((flags&(RFPROC|RFFDG|RFMEM)) == (RFPROC|RFFDG)){
                        /* check other flags before we commit */
                        flags &= ~(RFPROC|RFFDG);
       -                if(flags & ~(RFNOTEG|RFNAMEG)){
       -                        werrstr("unknown flags %08ux in rfork", flags);
       +                n = (flags & ~(RFNOTEG|RFNAMEG|RFNOWAIT));
       +                if(n){
       +                        werrstr("unknown flags %08ux in rfork", n);
                                return -1;
                        }
       +                if(flags&RFNOWAIT){
       +                        if(pipe(p) < 0)
       +                                return -1;
       +                }
                        pid = fork();
       +                if(pid == -1)
       +                        return -1;
       +                if(flags&RFNOWAIT){
       +                        flags &= ~RFNOWAIT;
       +                        if(pid){
       +                                /*
       +                                 * Parent - wait for child to fork wait-free child.
       +                                 * Then read pid from pipe.  Assume pipe buffer can absorb the write.
       +                                 */
       +                                close(p[1]);
       +                                wait4(pid, &status, 0, 0);
       +                                n = readn(p[0], buf, sizeof buf-1);
       +                                close(p[0]);
       +                                if(!WIFEXITED(status) || WEXITSTATUS(status)!=0 || n <= 0){
       +                                        werrstr("pipe dance failed in rfork");
       +                                        return -1;
       +                                }
       +                                buf[n] = 0;
       +                                n = strtol(buf, &q, 0);
       +                                if(*q != 0){
       +                                        werrstr("%s", q);
       +                                        return -1;
       +                                }
       +                                pid = n;
       +                        }else{
       +                                /*
       +                                 * Child - fork a new child whose wait message can't 
       +                                 * get back to the parent because we're going to exit!
       +                                 */
       +                                signal(SIGCHLD, SIG_IGN);
       +                                close(p[0]);
       +                                pid = fork();
       +                                if(pid){
       +                                        /* Child parent - send status over pipe and exit. */
       +                                        if(pid > 0)
       +                                                fprint(p[1], "%d", pid);
       +                                        else
       +                                                fprint(p[1], " %r");
       +                                        close(p[1]);
       +                                        _exit(0);
       +                                }else{
       +                                        /* Child child - close pipe. */
       +                                        close(p[1]);
       +                                }
       +                        }
       +                }
                        _p9uproc(0);
                        if(pid != 0)
                                return pid;
       t@@ -32,6 +89,10 @@ p9rfork(int flags)
                        setpgid(0, getpid());
                        flags &= ~RFNOTEG;
                }
       +        if(flags&RFNOWAIT){
       +                werrstr("cannot use RFNOWAIT without RFPROC");
       +                return -1;
       +        }
                if(flags){
                        werrstr("unknown flags %08ux in rfork", flags);
                        return -1;