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