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 06c4fd06 2004-04-21 devnull int n;
19 06c4fd06 2004-04-21 devnull char buf[128], *q;
20 1c8efa18 2003-12-04 devnull
21 1c8efa18 2003-12-04 devnull if((flags&(RFPROC|RFFDG|RFMEM)) == (RFPROC|RFFDG)){
22 1c8efa18 2003-12-04 devnull /* check other flags before we commit */
23 1c8efa18 2003-12-04 devnull flags &= ~(RFPROC|RFFDG);
24 06c4fd06 2004-04-21 devnull n = (flags & ~(RFNOTEG|RFNAMEG|RFNOWAIT));
25 06c4fd06 2004-04-21 devnull if(n){
26 06c4fd06 2004-04-21 devnull werrstr("unknown flags %08ux in rfork", n);
27 1c8efa18 2003-12-04 devnull return -1;
28 1c8efa18 2003-12-04 devnull }
29 06c4fd06 2004-04-21 devnull if(flags&RFNOWAIT){
30 32116738 2004-10-22 devnull /*
31 32116738 2004-10-22 devnull * BUG - should put the signal handler back after we
32 32116738 2004-10-22 devnull * finish, but I just don't care. If a program calls with
33 32116738 2004-10-22 devnull * NOWAIT once, they're not likely to want child notes
34 32116738 2004-10-22 devnull * after that.
35 32116738 2004-10-22 devnull */
36 32116738 2004-10-22 devnull signal(SIGCHLD, nop);
37 06c4fd06 2004-04-21 devnull if(pipe(p) < 0)
38 06c4fd06 2004-04-21 devnull return -1;
39 06c4fd06 2004-04-21 devnull }
40 1c8efa18 2003-12-04 devnull pid = fork();
41 06c4fd06 2004-04-21 devnull if(pid == -1)
42 06c4fd06 2004-04-21 devnull return -1;
43 06c4fd06 2004-04-21 devnull if(flags&RFNOWAIT){
44 06c4fd06 2004-04-21 devnull flags &= ~RFNOWAIT;
45 06c4fd06 2004-04-21 devnull if(pid){
46 06c4fd06 2004-04-21 devnull /*
47 06c4fd06 2004-04-21 devnull * Parent - wait for child to fork wait-free child.
48 06c4fd06 2004-04-21 devnull * Then read pid from pipe. Assume pipe buffer can absorb the write.
49 06c4fd06 2004-04-21 devnull */
50 06c4fd06 2004-04-21 devnull close(p[1]);
51 32116738 2004-10-22 devnull status = 0;
52 32116738 2004-10-22 devnull if(wait4(pid, &status, 0, 0) < 0){
53 32116738 2004-10-22 devnull werrstr("pipe dance - wait4 - %r");
54 32116738 2004-10-22 devnull close(p[0]);
55 32116738 2004-10-22 devnull return -1;
56 32116738 2004-10-22 devnull }
57 06c4fd06 2004-04-21 devnull n = readn(p[0], buf, sizeof buf-1);
58 06c4fd06 2004-04-21 devnull close(p[0]);
59 06c4fd06 2004-04-21 devnull if(!WIFEXITED(status) || WEXITSTATUS(status)!=0 || n <= 0){
60 32116738 2004-10-22 devnull if(!WIFEXITED(status))
61 32116738 2004-10-22 devnull werrstr("pipe dance - !exited 0x%ux", status);
62 32116738 2004-10-22 devnull else if(WEXITSTATUS(status) != 0)
63 32116738 2004-10-22 devnull werrstr("pipe dance - non-zero status 0x%ux", status);
64 32116738 2004-10-22 devnull else if(n < 0)
65 32116738 2004-10-22 devnull werrstr("pipe dance - pipe read error - %r");
66 32116738 2004-10-22 devnull else if(n == 0)
67 32116738 2004-10-22 devnull werrstr("pipe dance - pipe read eof");
68 32116738 2004-10-22 devnull else
69 32116738 2004-10-22 devnull werrstr("pipe dance - unknown failure");
70 06c4fd06 2004-04-21 devnull return -1;
71 06c4fd06 2004-04-21 devnull }
72 06c4fd06 2004-04-21 devnull buf[n] = 0;
73 32116738 2004-10-22 devnull if(buf[0] == 'x'){
74 32116738 2004-10-22 devnull werrstr("%s", buf+2);
75 06c4fd06 2004-04-21 devnull return -1;
76 06c4fd06 2004-04-21 devnull }
77 32116738 2004-10-22 devnull pid = strtol(buf, &q, 0);
78 06c4fd06 2004-04-21 devnull }else{
79 06c4fd06 2004-04-21 devnull /*
80 06c4fd06 2004-04-21 devnull * Child - fork a new child whose wait message can't
81 06c4fd06 2004-04-21 devnull * get back to the parent because we're going to exit!
82 06c4fd06 2004-04-21 devnull */
83 06c4fd06 2004-04-21 devnull signal(SIGCHLD, SIG_IGN);
84 06c4fd06 2004-04-21 devnull close(p[0]);
85 06c4fd06 2004-04-21 devnull pid = fork();
86 06c4fd06 2004-04-21 devnull if(pid){
87 06c4fd06 2004-04-21 devnull /* Child parent - send status over pipe and exit. */
88 06c4fd06 2004-04-21 devnull if(pid > 0)
89 06c4fd06 2004-04-21 devnull fprint(p[1], "%d", pid);
90 06c4fd06 2004-04-21 devnull else
91 32116738 2004-10-22 devnull fprint(p[1], "x %r");
92 06c4fd06 2004-04-21 devnull close(p[1]);
93 06c4fd06 2004-04-21 devnull _exit(0);
94 06c4fd06 2004-04-21 devnull }else{
95 06c4fd06 2004-04-21 devnull /* Child child - close pipe. */
96 06c4fd06 2004-04-21 devnull close(p[1]);
97 06c4fd06 2004-04-21 devnull }
98 06c4fd06 2004-04-21 devnull }
99 06c4fd06 2004-04-21 devnull }
100 1c8efa18 2003-12-04 devnull if(pid != 0)
101 1c8efa18 2003-12-04 devnull return pid;
102 1c8efa18 2003-12-04 devnull }
103 fd04aace 2003-11-23 devnull if(flags&RFPROC){
104 32f69c36 2003-12-11 devnull werrstr("cannot use rfork for shared memory -- use ffork");
105 fd04aace 2003-11-23 devnull return -1;
106 fd04aace 2003-11-23 devnull }
107 32f69c36 2003-12-11 devnull if(flags&RFNAMEG){
108 32f69c36 2003-12-11 devnull /* XXX set $NAMESPACE to a new directory */
109 32f69c36 2003-12-11 devnull flags &= ~RFNAMEG;
110 32f69c36 2003-12-11 devnull }
111 fd04aace 2003-11-23 devnull if(flags&RFNOTEG){
112 1c253ceb 2003-11-23 devnull setpgid(0, getpid());
113 fd04aace 2003-11-23 devnull flags &= ~RFNOTEG;
114 fd04aace 2003-11-23 devnull }
115 06c4fd06 2004-04-21 devnull if(flags&RFNOWAIT){
116 06c4fd06 2004-04-21 devnull werrstr("cannot use RFNOWAIT without RFPROC");
117 06c4fd06 2004-04-21 devnull return -1;
118 06c4fd06 2004-04-21 devnull }
119 fd04aace 2003-11-23 devnull if(flags){
120 fd04aace 2003-11-23 devnull werrstr("unknown flags %08ux in rfork", flags);
121 fd04aace 2003-11-23 devnull return -1;
122 fd04aace 2003-11-23 devnull }
123 fd04aace 2003-11-23 devnull return 0;
124 fd04aace 2003-11-23 devnull }