commit - ee6d04f9feec5011da240a9e08704c775806c331
commit + 06c4fd06cae9dd155eb284eac046f54d1c75bb24
blob - a3fe8df0e402791f6ab4a4658522c41bb4a4d796
blob + bdc8841f331f73cc7d6431858e5451ace4170c84
--- src/lib9/mkfile
+++ src/lib9/mkfile
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
#include <u.h>
+#include <sys/wait.h>
+#include <signal.h>
#include <libc.h>
#include "9proc.h"
#undef rfork
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;
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;