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;
12 static int gotsigchld;
14 static void
15 child(void)
16 {
17 int status, pid;
18 struct rlimit rl;
20 notedisable("sys: child");
21 pid = waitpid(sigpid, &status, 0);
22 if(pid < 0){
23 fprint(2, "%s: wait: %r\n", argv0);
24 _exit(97);
25 }
26 if(WIFEXITED(status))
27 _exit(WEXITSTATUS(status));
28 if(WIFSIGNALED(status)){
29 /*
30 * Make sure we don't scribble over the nice
31 * core file that our child just wrote out.
32 */
33 rl.rlim_cur = 0;
34 rl.rlim_max = 0;
35 setrlimit(RLIMIT_CORE, &rl);
37 signal(WTERMSIG(status), SIG_DFL);
38 raise(WTERMSIG(status));
39 _exit(98); /* not reached */
40 }
41 if(WIFSTOPPED(status)){
42 fprint(2, "%s: wait pid %d stopped\n", argv0, pid);
43 return;
44 }
45 #ifdef WIFCONTINUED
46 if(WIFCONTINUED(status)){
47 fprint(2, "%s: wait pid %d continued\n", argv0, pid);
48 return;
49 }
50 #endif
51 fprint(2, "%s: wait pid %d status 0x%ux\n", argv0, pid, status);
52 _exit(99);
53 }
55 static void
56 sigpass(int sig)
57 {
58 if(sigpid == 1){
59 gotsigchld = 1;
60 return;
61 }
63 if(sig == SIGCHLD)
64 child();
65 else
66 kill(sigpid, sig);
67 }
69 static int sigs[] =
70 {
71 SIGHUP, SIGINT, SIGQUIT, SIGILL,
72 SIGTRAP, SIGABRT, SIGBUS, SIGFPE,
73 SIGUSR1, SIGSEGV, SIGUSR2, SIGPIPE,
74 SIGALRM, SIGTERM, SIGCHLD, SIGSTOP,
75 /*SIGTSTP, SIGTTIN, SIGTTOU,*/ SIGURG,
76 SIGXCPU, SIGXFSZ, SIGVTALRM, SIGPROF,
77 #ifdef SIGWINCH
78 SIGWINCH,
79 #endif
80 #ifdef SIGIO
81 SIGIO,
82 #endif
83 #ifdef SIGEMT
84 SIGEMT,
85 #endif
86 #ifdef SIGPWR
87 SIGPWR,
88 #endif
89 #ifdef SIGINFO
90 SIGINFO,
91 #endif
92 SIGSYS
93 };
95 void
96 _threadsetupdaemonize(void)
97 {
98 int i, n, pid;
99 int p[2];
100 char buf[20];
102 sigpid = 1;
104 if(pipe(p) < 0)
105 sysfatal("passer pipe: %r");
107 /* hide these somewhere they won't cause harm */
108 /* can't go too high: NetBSD max is 64, for example */
109 if(dup(p[0], 28) < 0 || dup(p[1], 29) < 0)
110 sysfatal("passer pipe dup: %r");
111 close(p[0]);
112 close(p[1]);
113 p[0] = 28;
114 p[1] = 29;
116 /* close on exec */
117 if(fcntl(p[0], F_SETFD, 1) < 0 || fcntl(p[1], F_SETFD, 1) < 0)
118 sysfatal("passer pipe pipe fcntl: %r");
120 noteenable("sys: child");
121 signal(SIGCHLD, sigpass);
122 switch(pid = fork()){
123 case -1:
124 sysfatal("passer fork: %r");
125 default:
126 close(p[1]);
127 break;
128 case 0:
129 notedisable("sys: child");
130 signal(SIGCHLD, SIG_DFL);
131 /* rfork(RFNOTEG); */
132 close(p[0]);
133 threadpassfd = p[1];
134 return;
137 sigpid = pid;
138 if(gotsigchld)
139 sigpass(SIGCHLD);
141 for(i=0; i<nelem(sigs); i++){
142 struct sigaction sa;
144 memset(&sa, 0, sizeof sa);
145 sa.sa_handler = sigpass;
146 sa.sa_flags |= SA_RESTART;
147 sigaction(sigs[i], &sa, nil);
150 for(;;){
151 n = read(p[0], buf, sizeof buf-1);
152 if(n == 0){ /* program exited */
153 child();
155 if(n > 0)
156 break;
157 print("passer read: %r\n");
159 buf[n] = 0;
160 _exit(atoi(buf));
163 void
164 _threaddaemonize(void)
166 if(threadpassfd >= 0){
167 write(threadpassfd, "0", 1);
168 close(threadpassfd);
169 threadpassfd = -1;