Blob


1 #include <u.h>
2 #include <sys/time.h>
3 #include <sys/resource.h>
4 #include "threadimpl.h"
6 #undef waitpid
7 #undef pipe
8 #undef wait
10 static int sigpid;
11 static int threadpassfd;
13 static void
14 child(void)
15 {
16 int status, pid;
17 struct rlimit rl;
19 notedisable("sys: child");
20 pid = waitpid(sigpid, &status, 0);
21 if(pid < 0){
22 fprint(2, "%s: wait: %r\n", argv0);
23 _exit(97);
24 }
25 if(WIFEXITED(status))
26 _exit(WEXITSTATUS(status));
27 if(WIFSIGNALED(status)){
28 /*
29 * Make sure we don't scribble over the nice
30 * core file that our child just wrote out.
31 */
32 rl.rlim_cur = 0;
33 rl.rlim_max = 0;
34 setrlimit(RLIMIT_CORE, &rl);
36 signal(WTERMSIG(status), SIG_DFL);
37 raise(WTERMSIG(status));
38 _exit(98); /* not reached */
39 }
40 fprint(2, "%s: wait pid %d status 0x%ux\n", pid, status);
41 _exit(99);
42 }
44 static void
45 sigpass(int sig)
46 {
47 if(sig == SIGCHLD)
48 child();
49 else
50 kill(sigpid, sig);
51 }
53 void
54 _threadsetupdaemonize(void)
55 {
56 int i, n, pid;
57 int p[2];
58 char buf[20];
60 sigpid = 1;
62 threadlinklibrary();
64 if(pipe(p) < 0)
65 sysfatal("passer pipe: %r");
67 /* hide these somewhere they won't cause harm */
68 if(dup(p[0], 98) < 0 || dup(p[1], 99) < 0)
69 sysfatal("passer pipe dup: %r");
70 close(p[0]);
71 close(p[1]);
72 p[0] = 98;
73 p[1] = 99;
75 /* close on exec */
76 if(fcntl(p[0], F_SETFD, 1) < 0 || fcntl(p[1], F_SETFD, 1) < 0)
77 sysfatal("passer pipe pipe fcntl: %r");
79 noteenable("sys: child");
80 signal(SIGCHLD, sigpass);
81 switch(pid = fork()){
82 case -1:
83 sysfatal("passer fork: %r");
84 default:
85 close(p[1]);
86 break;
87 case 0:
88 for(i=0; i<100; i++) sched_yield();
89 notedisable("sys: child");
90 signal(SIGCHLD, SIG_DFL);
91 rfork(RFNOTEG);
92 close(p[0]);
93 threadpassfd = p[1];
94 return;
95 }
97 sigpid = pid;
98 for(i=0; i<NSIG; i++){
99 struct sigaction sa;
101 memset(&sa, 0, sizeof sa);
102 sa.sa_handler = sigpass;
103 sa.sa_flags |= SA_RESTART;
104 sigaction(i, &sa, nil);
107 for(;;){
108 n = read(p[0], buf, sizeof buf-1);
109 if(n == 0){ /* program exited */
110 child();
112 if(n > 0)
113 break;
114 print("passer read: %r\n");
116 buf[n] = 0;
117 _exit(atoi(buf));
120 void
121 _threaddaemonize(void)
123 if(threadpassfd >= 0){
124 write(threadpassfd, "0", 1);
125 close(threadpassfd);
126 threadpassfd = -1;