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