commit 06c4fd06cae9dd155eb284eac046f54d1c75bb24 from: rsc date: Wed Apr 21 22:44:37 2004 UTC add RFNOWAIT. this was probably a bad idea. commit - ee6d04f9feec5011da240a9e08704c775806c331 commit + 06c4fd06cae9dd155eb284eac046f54d1c75bb24 blob - a3fe8df0e402791f6ab4a4658522c41bb4a4d796 blob + bdc8841f331f73cc7d6431858e5451ace4170c84 --- src/lib9/mkfile +++ src/lib9/mkfile @@ -118,6 +118,7 @@ LIB9OFILES=\ mallocz.$O\ nan.$O\ needsrcquote.$O\ + needstack.$O\ netmkaddr.$O\ notify.$O\ nrand.$O\ blob - 21dc17e81ea579642d7b5ad3c3c2de6c79ca6f67 blob + d3c8f8b29895cb612fdef059f9c6b123d3eeefb3 --- src/lib9/rfork.c +++ src/lib9/rfork.c @@ -1,4 +1,6 @@ #include +#include +#include #include #include "9proc.h" #undef rfork @@ -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; @@ -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;