Blame


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
6 fd04aace 2003-11-23 devnull
7 32116738 2004-10-22 devnull static void
8 32116738 2004-10-22 devnull nop(int x)
9 32116738 2004-10-22 devnull {
10 32116738 2004-10-22 devnull USED(x);
11 32116738 2004-10-22 devnull }
12 32116738 2004-10-22 devnull
13 fd04aace 2003-11-23 devnull int
14 fd04aace 2003-11-23 devnull p9rfork(int flags)
15 fd04aace 2003-11-23 devnull {
16 06c4fd06 2004-04-21 devnull int pid, status;
17 06c4fd06 2004-04-21 devnull int p[2];
18 22ba8d1f 2006-02-12 devnull int n;
19 06c4fd06 2004-04-21 devnull char buf[128], *q;
20 e4d83222 2006-02-11 devnull extern char **environ;
21 1c8efa18 2003-12-04 devnull
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));
26 06c4fd06 2004-04-21 devnull if(n){
27 06c4fd06 2004-04-21 devnull werrstr("unknown flags %08ux in rfork", n);
28 1c8efa18 2003-12-04 devnull return -1;
29 1c8efa18 2003-12-04 devnull }
30 06c4fd06 2004-04-21 devnull if(flags&RFNOWAIT){
31 32116738 2004-10-22 devnull /*
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.
36 32116738 2004-10-22 devnull */
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;
40 06c4fd06 2004-04-21 devnull }
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;
46 06c4fd06 2004-04-21 devnull if(pid){
47 06c4fd06 2004-04-21 devnull /*
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.
50 06c4fd06 2004-04-21 devnull */
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;
57 32116738 2004-10-22 devnull }
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");
69 32116738 2004-10-22 devnull else
70 32116738 2004-10-22 devnull werrstr("pipe dance - unknown failure");
71 06c4fd06 2004-04-21 devnull return -1;
72 06c4fd06 2004-04-21 devnull }
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;
77 06c4fd06 2004-04-21 devnull }
78 32116738 2004-10-22 devnull pid = strtol(buf, &q, 0);
79 06c4fd06 2004-04-21 devnull }else{
80 06c4fd06 2004-04-21 devnull /*
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!
83 06c4fd06 2004-04-21 devnull */
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();
87 06c4fd06 2004-04-21 devnull if(pid){
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);
91 06c4fd06 2004-04-21 devnull else
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);
95 06c4fd06 2004-04-21 devnull }else{
96 06c4fd06 2004-04-21 devnull /* Child child - close pipe. */
97 06c4fd06 2004-04-21 devnull close(p[1]);
98 06c4fd06 2004-04-21 devnull }
99 06c4fd06 2004-04-21 devnull }
100 06c4fd06 2004-04-21 devnull }
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;
106 1c8efa18 2003-12-04 devnull }
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;
110 fd04aace 2003-11-23 devnull }
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;
114 32f69c36 2003-12-11 devnull }
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;
118 fd04aace 2003-11-23 devnull }
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;
122 06c4fd06 2004-04-21 devnull }
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;
126 fd04aace 2003-11-23 devnull }
127 fd04aace 2003-11-23 devnull return 0;
128 fd04aace 2003-11-23 devnull }