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 SIGWINCH, SIGIO,
78 #ifdef SIGEMT
79 SIGEMT,
80 #endif
81 #ifdef SIGPWR
82 SIGPWR,
83 #endif
84 #ifdef SIGINFO
85 SIGINFO,
86 #endif
87 SIGSYS
88 };
90 void
91 _threadsetupdaemonize(void)
92 {
93 int i, n, pid;
94 int p[2];
95 char buf[20];
97 sigpid = 1;
99 if(pipe(p) < 0)
100 sysfatal("passer pipe: %r");
102 /* hide these somewhere they won't cause harm */
103 /* can't go too high: NetBSD max is 64, for example */
104 if(dup(p[0], 28) < 0 || dup(p[1], 29) < 0)
105 sysfatal("passer pipe dup: %r");
106 close(p[0]);
107 close(p[1]);
108 p[0] = 28;
109 p[1] = 29;
111 /* close on exec */
112 if(fcntl(p[0], F_SETFD, 1) < 0 || fcntl(p[1], F_SETFD, 1) < 0)
113 sysfatal("passer pipe pipe fcntl: %r");
115 noteenable("sys: child");
116 signal(SIGCHLD, sigpass);
117 switch(pid = fork()){
118 case -1:
119 sysfatal("passer fork: %r");
120 default:
121 close(p[1]);
122 break;
123 case 0:
124 notedisable("sys: child");
125 signal(SIGCHLD, SIG_DFL);
126 /* rfork(RFNOTEG); */
127 close(p[0]);
128 threadpassfd = p[1];
129 return;
132 sigpid = pid;
133 if(gotsigchld)
134 sigpass(SIGCHLD);
136 for(i=0; i<nelem(sigs); i++){
137 struct sigaction sa;
139 memset(&sa, 0, sizeof sa);
140 sa.sa_handler = sigpass;
141 sa.sa_flags |= SA_RESTART;
142 sigaction(sigs[i], &sa, nil);
145 for(;;){
146 n = read(p[0], buf, sizeof buf-1);
147 if(n == 0){ /* program exited */
148 child();
150 if(n > 0)
151 break;
152 print("passer read: %r\n");
154 buf[n] = 0;
155 _exit(atoi(buf));
158 void
159 _threaddaemonize(void)
161 if(threadpassfd >= 0){
162 write(threadpassfd, "0", 1);
163 close(threadpassfd);
164 threadpassfd = -1;