Blob
1 #include <u.h>2 #include <sys/wait.h>3 #include <signal.h>4 #include <libc.h>5 #include "9proc.h"6 #undef rfork8 int9 p9rfork(int flags)10 {11 int pid, status;12 int p[2];13 int n;14 char buf[128], *q;16 _p9uproc(0);17 if((flags&(RFPROC|RFFDG|RFMEM)) == (RFPROC|RFFDG)){18 /* check other flags before we commit */19 flags &= ~(RFPROC|RFFDG);20 n = (flags & ~(RFNOTEG|RFNAMEG|RFNOWAIT));21 if(n){22 werrstr("unknown flags %08ux in rfork", n);23 return -1;24 }25 if(flags&RFNOWAIT){26 if(pipe(p) < 0)27 return -1;28 }29 pid = fork();30 if(pid == -1)31 return -1;32 if(flags&RFNOWAIT){33 flags &= ~RFNOWAIT;34 if(pid){35 /*36 * Parent - wait for child to fork wait-free child.37 * Then read pid from pipe. Assume pipe buffer can absorb the write.38 */39 close(p[1]);40 wait4(pid, &status, 0, 0);41 n = readn(p[0], buf, sizeof buf-1);42 close(p[0]);43 if(!WIFEXITED(status) || WEXITSTATUS(status)!=0 || n <= 0){44 werrstr("pipe dance failed in rfork");45 return -1;46 }47 buf[n] = 0;48 n = strtol(buf, &q, 0);49 if(*q != 0){50 werrstr("%s", q);51 return -1;52 }53 pid = n;54 }else{55 /*56 * Child - fork a new child whose wait message can't57 * get back to the parent because we're going to exit!58 */59 signal(SIGCHLD, SIG_IGN);60 close(p[0]);61 pid = fork();62 if(pid){63 /* Child parent - send status over pipe and exit. */64 if(pid > 0)65 fprint(p[1], "%d", pid);66 else67 fprint(p[1], " %r");68 close(p[1]);69 _exit(0);70 }else{71 /* Child child - close pipe. */72 close(p[1]);73 }74 }75 }76 _p9uproc(0);77 if(pid != 0)78 return pid;79 }80 if(flags&RFPROC){81 werrstr("cannot use rfork for shared memory -- use ffork");82 return -1;83 }84 if(flags&RFNAMEG){85 /* XXX set $NAMESPACE to a new directory */86 flags &= ~RFNAMEG;87 }88 if(flags&RFNOTEG){89 setpgid(0, getpid());90 flags &= ~RFNOTEG;91 }92 if(flags&RFNOWAIT){93 werrstr("cannot use RFNOWAIT without RFPROC");94 return -1;95 }96 if(flags){97 werrstr("unknown flags %08ux in rfork", flags);98 return -1;99 }100 return 0;101 }