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