1 175b8a53 2004-04-21 devnull #include <u.h>
2 06c4fd06 2004-04-21 devnull #include <sys/wait.h>
3 06c4fd06 2004-04-21 devnull #include <signal.h>
4 175b8a53 2004-04-21 devnull #include <libc.h>
5 175b8a53 2004-04-21 devnull #undef rfork
7 32116738 2004-10-22 devnull static void
8 32116738 2004-10-22 devnull nop(int x)
14 fd04aace 2003-11-23 devnull p9rfork(int flags)
16 06c4fd06 2004-04-21 devnull int pid, status;
17 06c4fd06 2004-04-21 devnull int p[2];
19 06c4fd06 2004-04-21 devnull char buf[128], *q;
20 e4d83222 2006-02-11 devnull extern char **environ;
22 1c8efa18 2003-12-04 devnull if((flags&(RFPROC|RFFDG|RFMEM)) == (RFPROC|RFFDG)){
23 1c8efa18 2003-12-04 devnull /* check other flags before we commit */
24 e4d83222 2006-02-11 devnull flags &= ~(RFPROC|RFFDG|RFENVG);
25 e4d83222 2006-02-11 devnull n = (flags & ~(RFNOTEG|RFNAMEG|RFNOWAIT|RFCENVG));
27 06c4fd06 2004-04-21 devnull werrstr("unknown flags %08ux in rfork", n);
28 1c8efa18 2003-12-04 devnull return -1;
30 06c4fd06 2004-04-21 devnull if(flags&RFNOWAIT){
32 32116738 2004-10-22 devnull * BUG - should put the signal handler back after we
33 32116738 2004-10-22 devnull * finish, but I just don't care. If a program calls with
34 32116738 2004-10-22 devnull * NOWAIT once, they're not likely to want child notes
35 32116738 2004-10-22 devnull * after that.
37 32116738 2004-10-22 devnull signal(SIGCHLD, nop);
38 06c4fd06 2004-04-21 devnull if(pipe(p) < 0)
39 06c4fd06 2004-04-21 devnull return -1;
41 1c8efa18 2003-12-04 devnull pid = fork();
42 06c4fd06 2004-04-21 devnull if(pid == -1)
43 06c4fd06 2004-04-21 devnull return -1;
44 06c4fd06 2004-04-21 devnull if(flags&RFNOWAIT){
45 06c4fd06 2004-04-21 devnull flags &= ~RFNOWAIT;
48 06c4fd06 2004-04-21 devnull * Parent - wait for child to fork wait-free child.
49 06c4fd06 2004-04-21 devnull * Then read pid from pipe. Assume pipe buffer can absorb the write.
51 06c4fd06 2004-04-21 devnull close(p[1]);
52 32116738 2004-10-22 devnull status = 0;
53 32116738 2004-10-22 devnull if(wait4(pid, &status, 0, 0) < 0){
54 32116738 2004-10-22 devnull werrstr("pipe dance - wait4 - %r");
55 32116738 2004-10-22 devnull close(p[0]);
56 32116738 2004-10-22 devnull return -1;
58 06c4fd06 2004-04-21 devnull n = readn(p[0], buf, sizeof buf-1);
59 06c4fd06 2004-04-21 devnull close(p[0]);
60 06c4fd06 2004-04-21 devnull if(!WIFEXITED(status) || WEXITSTATUS(status)!=0 || n <= 0){
61 32116738 2004-10-22 devnull if(!WIFEXITED(status))
62 32116738 2004-10-22 devnull werrstr("pipe dance - !exited 0x%ux", status);
63 32116738 2004-10-22 devnull else if(WEXITSTATUS(status) != 0)
64 32116738 2004-10-22 devnull werrstr("pipe dance - non-zero status 0x%ux", status);
65 32116738 2004-10-22 devnull else if(n < 0)
66 32116738 2004-10-22 devnull werrstr("pipe dance - pipe read error - %r");
67 32116738 2004-10-22 devnull else if(n == 0)
68 32116738 2004-10-22 devnull werrstr("pipe dance - pipe read eof");
70 32116738 2004-10-22 devnull werrstr("pipe dance - unknown failure");
71 06c4fd06 2004-04-21 devnull return -1;
73 06c4fd06 2004-04-21 devnull buf[n] = 0;
74 32116738 2004-10-22 devnull if(buf[0] == 'x'){
75 32116738 2004-10-22 devnull werrstr("%s", buf+2);
76 06c4fd06 2004-04-21 devnull return -1;
78 32116738 2004-10-22 devnull pid = strtol(buf, &q, 0);
81 06c4fd06 2004-04-21 devnull * Child - fork a new child whose wait message can't
82 06c4fd06 2004-04-21 devnull * get back to the parent because we're going to exit!
84 06c4fd06 2004-04-21 devnull signal(SIGCHLD, SIG_IGN);
85 06c4fd06 2004-04-21 devnull close(p[0]);
86 06c4fd06 2004-04-21 devnull pid = fork();
88 06c4fd06 2004-04-21 devnull /* Child parent - send status over pipe and exit. */
89 06c4fd06 2004-04-21 devnull if(pid > 0)
90 06c4fd06 2004-04-21 devnull fprint(p[1], "%d", pid);
92 32116738 2004-10-22 devnull fprint(p[1], "x %r");
93 06c4fd06 2004-04-21 devnull close(p[1]);
94 06c4fd06 2004-04-21 devnull _exit(0);
96 06c4fd06 2004-04-21 devnull /* Child child - close pipe. */
97 06c4fd06 2004-04-21 devnull close(p[1]);
101 1c8efa18 2003-12-04 devnull if(pid != 0)
102 1c8efa18 2003-12-04 devnull return pid;
103 e4d83222 2006-02-11 devnull if(flags&RFCENVG)
104 e4d83222 2006-02-11 devnull if(environ)
105 e4d83222 2006-02-11 devnull *environ = nil;
107 fd04aace 2003-11-23 devnull if(flags&RFPROC){
108 cd374519 2005-10-29 devnull werrstr("cannot use rfork for shared memory -- use libthread");
109 fd04aace 2003-11-23 devnull return -1;
111 32f69c36 2003-12-11 devnull if(flags&RFNAMEG){
112 32f69c36 2003-12-11 devnull /* XXX set $NAMESPACE to a new directory */
113 32f69c36 2003-12-11 devnull flags &= ~RFNAMEG;
115 fd04aace 2003-11-23 devnull if(flags&RFNOTEG){
116 1c253ceb 2003-11-23 devnull setpgid(0, getpid());
117 fd04aace 2003-11-23 devnull flags &= ~RFNOTEG;
119 06c4fd06 2004-04-21 devnull if(flags&RFNOWAIT){
120 06c4fd06 2004-04-21 devnull werrstr("cannot use RFNOWAIT without RFPROC");
121 06c4fd06 2004-04-21 devnull return -1;
123 fd04aace 2003-11-23 devnull if(flags){
124 fd04aace 2003-11-23 devnull werrstr("unknown flags %08ux in rfork", flags);
125 fd04aace 2003-11-23 devnull return -1;
127 fd04aace 2003-11-23 devnull return 0;