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 = -1;
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 /*
105 * We've been told this program is likely to background itself.
106 * Put it in its own process group so that we don't get a SIGHUP
107 * when the parent exits.
108 */
109 setpgid(0, 0);
111 if(pipe(p) < 0)
112 sysfatal("passer pipe: %r");
114 /* hide these somewhere they won't cause harm */
115 /* can't go too high: NetBSD max is 64, for example */
116 if(dup(p[0], 28) < 0 || dup(p[1], 29) < 0)
117 sysfatal("passer pipe dup: %r");
118 close(p[0]);
119 close(p[1]);
120 p[0] = 28;
121 p[1] = 29;
123 /* close on exec */
124 if(fcntl(p[0], F_SETFD, 1) < 0 || fcntl(p[1], F_SETFD, 1) < 0)
125 sysfatal("passer pipe pipe fcntl: %r");
127 noteenable("sys: child");
128 signal(SIGCHLD, sigpass);
129 switch(pid = fork()){
130 case -1:
131 sysfatal("passer fork: %r");
132 default:
133 close(p[1]);
134 break;
135 case 0:
136 notedisable("sys: child");
137 signal(SIGCHLD, SIG_DFL);
138 /* rfork(RFNOTEG); */
139 close(p[0]);
140 threadpassfd = p[1];
141 return;
144 sigpid = pid;
145 if(gotsigchld)
146 sigpass(SIGCHLD);
148 for(i=0; i<nelem(sigs); i++){
149 struct sigaction sa;
151 memset(&sa, 0, sizeof sa);
152 sa.sa_handler = sigpass;
153 sa.sa_flags |= SA_RESTART;
154 sigaction(sigs[i], &sa, nil);
157 for(;;){
158 n = read(p[0], buf, sizeof buf-1);
159 if(n == 0){ /* program exited */
160 child();
162 if(n > 0)
163 break;
164 print("passer read: %r\n");
166 buf[n] = 0;
167 _exit(atoi(buf));
170 void
171 _threaddaemonize(void)
173 if(threadpassfd < 0)
174 sysfatal("threads in main proc exited w/o threadmaybackground");
175 write(threadpassfd, "0", 1);
176 close(threadpassfd);
177 threadpassfd = -1;