Mercurial > hg > nginx
comparison src/os/unix/ngx_process.c @ 218:05592fd7a436
nginx-0.0.1-2004-01-05-23:55:48 import
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Mon, 05 Jan 2004 20:55:48 +0000 |
parents | 8dee38ea9117 |
children | f57597ec5249 |
comparison
equal
deleted
inserted
replaced
217:c5d1cdcb04ec | 218:05592fd7a436 |
---|---|
1 | 1 |
2 #include <ngx_config.h> | 2 #include <ngx_config.h> |
3 #include <ngx_core.h> | 3 #include <ngx_core.h> |
4 | 4 |
5 | 5 |
6 void testone(ngx_log_t *log) | 6 static void ngx_exec_proc(ngx_cycle_t *cycle, void *data); |
7 { | 7 |
8 ngx_log_debug(log, "child process"); | 8 ngx_uint_t ngx_last_process; |
9 ngx_msleep(5000); | 9 ngx_process_t ngx_processes[NGX_MAX_PROCESSES]; |
10 exit(0); | 10 |
11 } | 11 |
12 | 12 ngx_int_t ngx_spawn_process(ngx_cycle_t *cycle, |
13 | 13 ngx_spawn_proc_pt proc, void *data, |
14 int ngx_spawn_process(ngx_log_t *log) | 14 char *name, ngx_int_t respawn) |
15 { | 15 { |
16 pid_t pid; | 16 sigset_t set, oset; |
17 sigset_t set, oset; | 17 ngx_pid_t pid; |
18 | |
19 if (respawn < 0) { | |
20 sigemptyset(&set); | |
21 sigaddset(&set, SIGCHLD); | |
22 if (sigprocmask(SIG_BLOCK, &set, &oset) == -1) { | |
23 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, | |
24 "sigprocmask() failed while spawning %s", name); | |
25 return NGX_ERROR; | |
26 } | |
27 } | |
28 | |
29 pid = fork(); | |
30 | |
31 if (pid == -1) { | |
32 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, | |
33 "fork() failed while spawning \"%s\"", name); | |
34 } | |
35 | |
36 if (pid == -1 || pid == 0) { | |
37 if (sigprocmask(SIG_SETMASK, &oset, &set) == -1) { | |
38 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, | |
39 "sigprocmask() failed while spawning %s", name); | |
40 return NGX_ERROR; | |
41 } | |
42 } | |
43 | |
44 switch (pid) { | |
45 case -1: | |
46 return NGX_ERROR; | |
47 | |
48 case 0: | |
49 proc(cycle, data); | |
50 break; | |
51 | |
52 default: | |
53 break; | |
54 } | |
55 | |
56 ngx_log_debug2(NGX_LOG_DEBUG_CORE, cycle->log, 0, | |
57 "spawn %s: " PID_T_FMT, name, pid); | |
58 | |
59 if (respawn >= 0) { | |
60 ngx_processes[respawn].pid = pid; | |
61 ngx_processes[respawn].exited = 0; | |
62 return NGX_OK; | |
63 } | |
64 | |
65 ngx_processes[ngx_last_process].pid = pid; | |
66 ngx_processes[ngx_last_process].proc = proc; | |
67 ngx_processes[ngx_last_process].data = data; | |
68 ngx_processes[ngx_last_process].name = name; | |
69 ngx_processes[ngx_last_process].respawn = | |
70 (respawn == NGX_PROCESS_RESPAWN) ? 1 : 0; | |
71 ngx_processes[ngx_last_process].detached = | |
72 (respawn == NGX_PROCESS_DETACHED) ? 1 : 0; | |
73 ngx_processes[ngx_last_process].exited = 0; | |
74 ngx_processes[ngx_last_process].exiting = 0; | |
75 ngx_last_process++; | |
76 | |
77 if (sigprocmask(SIG_SETMASK, &oset, &set) == -1) { | |
78 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, | |
79 "sigprocmask() failed while spawning %s", name); | |
80 return NGX_ERROR; | |
81 } | |
82 | |
83 return NGX_OK; | |
84 } | |
85 | |
86 | |
87 ngx_int_t ngx_exec(ngx_cycle_t *cycle, ngx_exec_ctx_t *ctx) | |
88 { | |
89 if (ngx_spawn_process(cycle, ngx_exec_proc, ctx, ctx->name, | |
90 NGX_PROCESS_DETACHED) == NGX_ERROR) | |
91 { | |
92 ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, | |
93 "can not spawn %s", ctx->name); | |
94 return NGX_ERROR; | |
95 } | |
96 | |
97 return NGX_OK; | |
98 } | |
99 | |
100 | |
101 static void ngx_exec_proc(ngx_cycle_t *cycle, void *data) | |
102 { | |
103 ngx_exec_ctx_t *ctx = data; | |
104 | |
105 if (execve(ctx->path, ctx->argv, ctx->envp) == -1) { | |
106 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, | |
107 "execve() failed while executing %s \"%s\"", | |
108 ctx->name, ctx->path); | |
109 } | |
110 | |
111 exit(1); | |
112 } | |
113 | |
114 | |
115 void ngx_signal_processes(ngx_cycle_t *cycle, ngx_int_t signal) | |
116 { | |
117 sigset_t set, oset; | |
118 ngx_uint_t i; | |
18 | 119 |
19 sigemptyset(&set); | 120 sigemptyset(&set); |
20 sigaddset(&set, SIGCHLD); | 121 sigaddset(&set, SIGCHLD); |
21 if (sigprocmask(SIG_BLOCK, &set, &oset) == -1) { | 122 if (sigprocmask(SIG_BLOCK, &set, &oset) == -1) { |
22 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, "sigprocmask() failed"); | 123 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, |
23 } | 124 "sigprocmask() failed while signaling processes"); |
24 | 125 return; |
25 pid = fork(); | 126 } |
26 | 127 |
27 if (pid == -1 || pid == 0) { | 128 for (i = 0; i < ngx_last_process; i++) { |
28 if (sigprocmask(SIG_SETMASK, &oset, &set) == -1) { | 129 |
29 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, | 130 if (ngx_processes[i].detached) { |
30 "sigprocmask() failed"); | 131 continue; |
31 } | 132 } |
32 } | 133 |
33 | 134 if (ngx_processes[i].exited) { |
34 switch (pid) { | 135 if (i != --ngx_last_process) { |
35 case -1: | 136 ngx_processes[i--] = ngx_processes[ngx_last_process]; |
36 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, "fork() failed"); | 137 } |
37 return NGX_ERROR; | 138 continue; |
38 | 139 } |
39 case 0: | 140 |
40 testone(log); | 141 ngx_log_debug2(NGX_LOG_DEBUG_CORE, cycle->log, 0, |
41 break; | 142 "kill (" PID_T_FMT ", %d)" , |
42 | 143 ngx_processes[i].pid, signal); |
43 default: | 144 |
44 break; | 145 if (kill(ngx_processes[i].pid, signal) == -1) { |
45 } | 146 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, |
46 | 147 "kill(%d, %d) failed", ngx_processes[i].pid, signal); |
47 ngx_log_debug(log, "parent process, child: " PID_T_FMT _ pid); | 148 continue; |
48 | 149 } |
49 /* book keeping */ | 150 |
151 if (signal != ngx_signal_value(NGX_REOPEN_SIGNAL)) { | |
152 ngx_processes[i].exiting = 1; | |
153 } | |
154 } | |
50 | 155 |
51 if (sigprocmask(SIG_SETMASK, &oset, &set) == -1) { | 156 if (sigprocmask(SIG_SETMASK, &oset, &set) == -1) { |
52 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, "sigprocmask() failed"); | 157 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, |
53 } | 158 "sigprocmask() failed while signaling processes"); |
54 | 159 } |
55 return NGX_OK; | 160 } |
56 } | 161 |
57 | 162 |
58 | 163 void ngx_respawn_processes(ngx_cycle_t *cycle) |
164 { | |
165 sigset_t set, oset; | |
166 ngx_uint_t i; | |
167 | |
168 sigemptyset(&set); | |
169 sigaddset(&set, SIGCHLD); | |
170 if (sigprocmask(SIG_BLOCK, &set, &oset) == -1) { | |
171 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, | |
172 "sigprocmask() failed while respawning processes"); | |
173 return; | |
174 } | |
175 | |
176 /* | |
177 * to avoid a race condition we can check and set value of ngx_respawn | |
178 * only in signal handler or while SIGCHLD is blocked | |
179 */ | |
180 | |
181 if (ngx_respawn) { | |
182 | |
183 for (i = 0; i < ngx_last_process; i++) { | |
184 if (!ngx_processes[i].exited) { | |
185 continue; | |
186 } | |
187 | |
188 if (!ngx_processes[i].respawn) { | |
189 if (i != --ngx_last_process) { | |
190 ngx_processes[i--] = ngx_processes[ngx_last_process]; | |
191 } | |
192 continue; | |
193 } | |
194 | |
195 if (ngx_spawn_process(cycle, | |
196 ngx_processes[i].proc, ngx_processes[i].data, | |
197 ngx_processes[i].name, i) == NGX_ERROR) | |
198 { | |
199 ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, | |
200 "can not respawn %s", ngx_processes[i].name); | |
201 } | |
202 } | |
203 | |
204 ngx_respawn = 0; | |
205 } | |
206 | |
207 if (sigprocmask(SIG_SETMASK, &oset, &set) == -1) { | |
208 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, | |
209 "sigprocmask() failed while respawning processes"); | |
210 } | |
211 } | |
212 | |
213 | |
214 #if 0 | |
59 void ngx_sigchld_handler(int signo) | 215 void ngx_sigchld_handler(int signo) |
60 { | 216 { |
61 int status, one; | 217 int status; |
62 pid_t pid; | 218 char *process; |
63 ngx_err_t err; | 219 ngx_pid_t pid; |
64 struct timeval tv; | 220 ngx_err_t err; |
221 ngx_uint_t i, one; | |
222 struct timeval tv; | |
65 | 223 |
66 ngx_gettimeofday(&tv); | 224 ngx_gettimeofday(&tv); |
67 | 225 ngx_time_update(tv.tv_sec); |
68 if (ngx_cached_time != tv.tv_sec) { | 226 |
69 ngx_cached_time = tv.tv_sec; | 227 ngx_log_error(NGX_LOG_INFO, ngx_cycle->log, 0, |
70 ngx_time_update(); | 228 "signal #%d (SIGCHLD) received", signo); |
71 } | 229 } |
72 | 230 #endif |
231 | |
232 | |
233 void ngx_process_get_status() | |
234 { | |
235 int status; | |
236 char *process; | |
237 ngx_pid_t pid; | |
238 ngx_err_t err; | |
239 ngx_uint_t i, one; | |
240 struct timeval tv; | |
73 one = 0; | 241 one = 0; |
74 | 242 |
75 for ( ;; ) { | 243 for ( ;; ) { |
76 pid = waitpid(-1, &status, WNOHANG); | 244 pid = waitpid(-1, &status, WNOHANG); |
77 | 245 |
94 "waitpid() failed"); | 262 "waitpid() failed"); |
95 return; | 263 return; |
96 } | 264 } |
97 | 265 |
98 one = 1; | 266 one = 1; |
99 | 267 process = ""; |
100 ngx_log_error(NGX_LOG_INFO, ngx_cycle->log, 0, | 268 |
101 "process " PID_T_FMT " exited with code %d", pid, status); | 269 for (i = 0; i < ngx_last_process; i++) { |
102 | 270 if (ngx_processes[i].pid == pid) { |
103 /* TODO: restart handler */ | 271 ngx_processes[i].status = status; |
104 | 272 |
105 #if 0 | 273 if (!ngx_processes[i].exiting) { |
106 ngx_msleep(2000); | 274 ngx_processes[i].exited = 1; |
107 #endif | 275 |
108 | 276 if (ngx_processes[i].respawn) { |
109 #if 0 | 277 ngx_respawn = 1; |
110 ngx_spawn_process(ngx_cycle->log); | 278 } |
111 #endif | 279 } |
112 } | 280 |
113 } | 281 process = ngx_processes[i].name; |
282 break; | |
283 } | |
284 } | |
285 | |
286 if (i == ngx_last_process) { | |
287 process = "unknown process"; | |
288 } | |
289 | |
290 if (WTERMSIG(status)) { | |
291 ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0, | |
292 "%s " PID_T_FMT " exited on signal %d%s", | |
293 process, pid, WTERMSIG(status), | |
294 WCOREDUMP(status) ? " (core dumped)" : ""); | |
295 | |
296 } else { | |
297 ngx_log_error(NGX_LOG_INFO, ngx_cycle->log, 0, | |
298 "%s " PID_T_FMT " exited with code %d", | |
299 process, pid, WEXITSTATUS(status)); | |
300 } | |
301 } | |
302 } |