Mercurial > hg > nginx
comparison src/os/unix/ngx_process_cycle.c @ 278:0ba4821f4460
nginx-0.0.2-2004-03-04-10:04:55 import
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Thu, 04 Mar 2004 07:04:55 +0000 |
parents | |
children | b79f021a644a |
comparison
equal
deleted
inserted
replaced
277:e91499541410 | 278:0ba4821f4460 |
---|---|
1 | |
2 #include <ngx_config.h> | |
3 #include <ngx_core.h> | |
4 #include <ngx_event.h> | |
5 | |
6 | |
7 static void ngx_master_exit(ngx_cycle_t *cycle, ngx_master_ctx_t *ctx); | |
8 static void ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data); | |
9 #if (NGX_THREADS) | |
10 static int ngx_worker_thread_cycle(void *data); | |
11 #endif | |
12 | |
13 | |
14 ngx_int_t ngx_process; | |
15 ngx_pid_t ngx_pid; | |
16 ngx_pid_t ngx_new_binary; | |
17 ngx_int_t ngx_inherited; | |
18 | |
19 sig_atomic_t ngx_reap; | |
20 sig_atomic_t ngx_timer; | |
21 sig_atomic_t ngx_terminate; | |
22 sig_atomic_t ngx_quit; | |
23 sig_atomic_t ngx_noaccept; | |
24 sig_atomic_t ngx_reconfigure; | |
25 sig_atomic_t ngx_reopen; | |
26 sig_atomic_t ngx_change_binary; | |
27 | |
28 | |
29 /* TODO: broken NGX_PROCESS_SINGLE */ | |
30 | |
31 void ngx_master_process_cycle(ngx_cycle_t *cycle, ngx_master_ctx_t *ctx) | |
32 { | |
33 int signo; | |
34 sigset_t set; | |
35 struct timeval tv; | |
36 struct itimerval itv; | |
37 ngx_uint_t i, live; | |
38 ngx_msec_t delay; | |
39 ngx_core_conf_t *ccf; | |
40 | |
41 sigemptyset(&set); | |
42 sigaddset(&set, SIGCHLD); | |
43 sigaddset(&set, SIGALRM); | |
44 sigaddset(&set, SIGINT); | |
45 sigaddset(&set, ngx_signal_value(NGX_RECONFIGURE_SIGNAL)); | |
46 sigaddset(&set, ngx_signal_value(NGX_REOPEN_SIGNAL)); | |
47 sigaddset(&set, ngx_signal_value(NGX_NOACCEPT_SIGNAL)); | |
48 sigaddset(&set, ngx_signal_value(NGX_TERMINATE_SIGNAL)); | |
49 sigaddset(&set, ngx_signal_value(NGX_SHUTDOWN_SIGNAL)); | |
50 sigaddset(&set, ngx_signal_value(NGX_CHANGEBIN_SIGNAL)); | |
51 | |
52 if (sigprocmask(SIG_BLOCK, &set, NULL) == -1) { | |
53 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, | |
54 "sigprocmask() failed"); | |
55 } | |
56 | |
57 sigemptyset(&set); | |
58 | |
59 ngx_setproctitle("master process"); | |
60 | |
61 ngx_new_binary = 0; | |
62 delay = 0; | |
63 signo = 0; | |
64 live = 0; | |
65 | |
66 for ( ;; ) { | |
67 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "new cycle"); | |
68 | |
69 if (ngx_process == NGX_PROCESS_MASTER) { | |
70 ngx_spawn_process(cycle, ngx_worker_process_cycle, NULL, | |
71 "worker process", NGX_PROCESS_RESPAWN); | |
72 | |
73 /* | |
74 * we have to limit the maximum life time of the worker processes | |
75 * by 1 month because our millisecond event timer is limited | |
76 * by 49 days on 32-bit platforms | |
77 */ | |
78 | |
79 itv.it_interval.tv_sec = 0; | |
80 itv.it_interval.tv_usec = 0; | |
81 itv.it_value.tv_sec = 30 * 24 * 60 * 60; | |
82 itv.it_value.tv_usec = 0; | |
83 | |
84 if (setitimer(ITIMER_REAL, &itv, NULL) == -1) { | |
85 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, | |
86 "setitimer() failed"); | |
87 } | |
88 | |
89 live = 1; | |
90 | |
91 } else { | |
92 ngx_init_temp_number(); | |
93 | |
94 for (i = 0; ngx_modules[i]; i++) { | |
95 if (ngx_modules[i]->init_process) { | |
96 if (ngx_modules[i]->init_process(cycle) == NGX_ERROR) { | |
97 /* fatal */ | |
98 exit(1); | |
99 } | |
100 } | |
101 } | |
102 } | |
103 | |
104 ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, | |
105 ngx_core_module); | |
106 | |
107 /* a cycle with the same configuration because a new one is invalid */ | |
108 | |
109 for ( ;; ) { | |
110 | |
111 /* an event loop */ | |
112 | |
113 for ( ;; ) { | |
114 | |
115 if (ngx_process == NGX_PROCESS_MASTER) { | |
116 if (delay) { | |
117 delay *= 2; | |
118 | |
119 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, | |
120 "temination cycle: %d", delay); | |
121 | |
122 itv.it_interval.tv_sec = 0; | |
123 itv.it_interval.tv_usec = 0; | |
124 itv.it_value.tv_sec = delay / 1000; | |
125 itv.it_value.tv_usec = (delay % 1000 ) * 1000; | |
126 | |
127 if (setitimer(ITIMER_REAL, &itv, NULL) == -1) { | |
128 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, | |
129 "setitimer() failed"); | |
130 } | |
131 } | |
132 | |
133 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, | |
134 "sigsuspend"); | |
135 | |
136 sigsuspend(&set); | |
137 | |
138 ngx_gettimeofday(&tv); | |
139 ngx_time_update(tv.tv_sec); | |
140 | |
141 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, | |
142 "wake up"); | |
143 | |
144 } else { /* NGX_PROCESS_SINGLE */ | |
145 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, | |
146 "worker cycle"); | |
147 | |
148 ngx_process_events(cycle->log); | |
149 live = 0; | |
150 } | |
151 | |
152 if (ngx_reap) { | |
153 ngx_reap = 0; | |
154 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, | |
155 "reap childs"); | |
156 | |
157 live = 0; | |
158 for (i = 0; i < ngx_last_process; i++) { | |
159 | |
160 ngx_log_debug5(NGX_LOG_DEBUG_EVENT, cycle->log, 0, | |
161 "child: " PID_T_FMT | |
162 " e:%d t:%d d:%d r:%d", | |
163 ngx_processes[i].pid, | |
164 ngx_processes[i].exiting, | |
165 ngx_processes[i].exited, | |
166 ngx_processes[i].detached, | |
167 ngx_processes[i].respawn); | |
168 | |
169 if (ngx_processes[i].exited) { | |
170 | |
171 if (ngx_processes[i].respawn | |
172 && !ngx_processes[i].exiting | |
173 && !ngx_terminate | |
174 && !ngx_quit) | |
175 { | |
176 if (ngx_spawn_process(cycle, | |
177 ngx_processes[i].proc, | |
178 ngx_processes[i].data, | |
179 ngx_processes[i].name, i) | |
180 == NGX_ERROR) | |
181 { | |
182 ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, | |
183 "can not respawn %s", | |
184 ngx_processes[i].name); | |
185 continue; | |
186 } | |
187 | |
188 live = 1; | |
189 | |
190 continue; | |
191 } | |
192 | |
193 if (ngx_processes[i].pid == ngx_new_binary) { | |
194 ngx_new_binary = 0; | |
195 | |
196 /* TODO: if (ngx_noaccept) ngx_configure = 1 */ | |
197 } | |
198 | |
199 if (i != --ngx_last_process) { | |
200 ngx_processes[i--] = | |
201 ngx_processes[ngx_last_process]; | |
202 } | |
203 | |
204 } else if (ngx_processes[i].exiting | |
205 || !ngx_processes[i].detached) | |
206 { | |
207 live = 1; | |
208 } | |
209 } | |
210 } | |
211 | |
212 if (!live && (ngx_terminate || ngx_quit)) { | |
213 ngx_master_exit(cycle, ctx); | |
214 } | |
215 | |
216 if (ngx_terminate) { | |
217 if (delay == 0) { | |
218 delay = 50; | |
219 } | |
220 | |
221 if (delay > 1000) { | |
222 signo = SIGKILL; | |
223 } else { | |
224 signo = ngx_signal_value(NGX_TERMINATE_SIGNAL); | |
225 } | |
226 | |
227 } else if (ngx_quit) { | |
228 signo = ngx_signal_value(NGX_SHUTDOWN_SIGNAL); | |
229 | |
230 } else if (ngx_timer) { | |
231 signo = ngx_signal_value(NGX_SHUTDOWN_SIGNAL); | |
232 | |
233 } else { | |
234 | |
235 if (ngx_noaccept) { | |
236 signo = ngx_signal_value(NGX_SHUTDOWN_SIGNAL); | |
237 } | |
238 | |
239 if (ngx_change_binary) { | |
240 ngx_change_binary = 0; | |
241 ngx_log_error(NGX_LOG_INFO, cycle->log, 0, | |
242 "changing binary"); | |
243 ngx_new_binary = ngx_exec_new_binary(cycle, ctx->argv); | |
244 } | |
245 | |
246 if (ngx_reconfigure) { | |
247 signo = ngx_signal_value(NGX_SHUTDOWN_SIGNAL); | |
248 ngx_log_error(NGX_LOG_INFO, cycle->log, 0, | |
249 "reconfiguring"); | |
250 } | |
251 | |
252 if (ngx_reopen) { | |
253 if (ngx_process == NGX_PROCESS_MASTER) { | |
254 if (ccf->worker_reopen != 0) { | |
255 signo = ngx_signal_value(NGX_REOPEN_SIGNAL); | |
256 ngx_reopen = 0; | |
257 | |
258 } else if (ngx_noaccept) { | |
259 ngx_reopen = 0; | |
260 | |
261 } else { | |
262 signo = ngx_signal_value(NGX_SHUTDOWN_SIGNAL); | |
263 } | |
264 | |
265 } else { /* NGX_PROCESS_SINGLE */ | |
266 ngx_reopen = 0; | |
267 } | |
268 | |
269 ngx_log_error(NGX_LOG_INFO, cycle->log, 0, | |
270 "reopening logs"); | |
271 ngx_reopen_files(cycle, | |
272 ccf->worker_reopen != 0 ? ccf->user : (uid_t) -1); | |
273 } | |
274 } | |
275 | |
276 if (signo) { | |
277 for (i = 0; i < ngx_last_process; i++) { | |
278 | |
279 if (ngx_processes[i].detached) { | |
280 continue; | |
281 } | |
282 | |
283 ngx_log_debug2(NGX_LOG_DEBUG_CORE, cycle->log, 0, | |
284 "kill (" PID_T_FMT ", %d)" , | |
285 ngx_processes[i].pid, signo); | |
286 | |
287 if (kill(ngx_processes[i].pid, signo) == -1) { | |
288 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, | |
289 "kill(%d, %d) failed", | |
290 ngx_processes[i].pid, signo); | |
291 continue; | |
292 } | |
293 | |
294 if (signo != ngx_signal_value(NGX_REOPEN_SIGNAL)) { | |
295 ngx_processes[i].exiting = 1; | |
296 } | |
297 } | |
298 | |
299 signo = 0; | |
300 } | |
301 | |
302 if (ngx_reopen || ngx_reconfigure || ngx_timer) { | |
303 break; | |
304 } | |
305 } | |
306 | |
307 if (ngx_reopen) { | |
308 ngx_reopen = 0; | |
309 | |
310 } else if (ngx_timer) { | |
311 ngx_timer = 0; | |
312 | |
313 } else if (ngx_noaccept) { | |
314 ngx_noaccept = 0; | |
315 ngx_reconfigure = 0; | |
316 | |
317 } else { | |
318 cycle = ngx_init_cycle(cycle); | |
319 if (cycle == NULL) { | |
320 cycle = (ngx_cycle_t *) ngx_cycle; | |
321 continue; | |
322 } | |
323 | |
324 ngx_cycle = cycle; | |
325 ngx_reconfigure = 0; | |
326 } | |
327 | |
328 break; | |
329 } | |
330 } | |
331 } | |
332 | |
333 | |
334 static void ngx_master_exit(ngx_cycle_t *cycle, ngx_master_ctx_t *ctx) | |
335 { | |
336 char *name; | |
337 | |
338 if (ngx_inherited && getppid() > 1) { | |
339 name = ctx->pid.name.data; | |
340 | |
341 } else { | |
342 name = ctx->name; | |
343 } | |
344 | |
345 if (ngx_delete_file(name) == NGX_FILE_ERROR) { | |
346 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, | |
347 ngx_delete_file_n " \"%s\" failed", name); | |
348 } | |
349 | |
350 ngx_log_error(NGX_LOG_INFO, cycle->log, 0, "exit"); | |
351 exit(0); | |
352 } | |
353 | |
354 | |
355 static void ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data) | |
356 { | |
357 sigset_t set; | |
358 ngx_int_t i; | |
359 ngx_listening_t *ls; | |
360 ngx_core_conf_t *ccf; | |
361 #if (NGX_THREADS) | |
362 ngx_tid_t tid; | |
363 #endif | |
364 | |
365 ngx_process = NGX_PROCESS_WORKER; | |
366 ngx_last_process = 0; | |
367 | |
368 ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); | |
369 | |
370 if (ccf->group != (gid_t) NGX_CONF_UNSET) { | |
371 if (setuid(ccf->group) == -1) { | |
372 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, | |
373 "setgid(%d) failed", ccf->group); | |
374 /* fatal */ | |
375 exit(2); | |
376 } | |
377 } | |
378 | |
379 if (ccf->user != (uid_t) NGX_CONF_UNSET && geteuid() == 0) { | |
380 if (setuid(ccf->user) == -1) { | |
381 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, | |
382 "setuid(%d) failed", ccf->user); | |
383 /* fatal */ | |
384 exit(2); | |
385 } | |
386 } | |
387 | |
388 #if (HAVE_PR_SET_DUMPABLE) | |
389 | |
390 /* allow coredump after setuid() in Linux 2.4.x */ | |
391 | |
392 if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) == -1) { | |
393 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, | |
394 "prctl(PR_SET_DUMPABLE) failed"); | |
395 } | |
396 | |
397 #endif | |
398 | |
399 sigemptyset(&set); | |
400 | |
401 if (sigprocmask(SIG_SETMASK, &set, NULL) == -1) { | |
402 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, | |
403 "sigprocmask() failed"); | |
404 } | |
405 | |
406 ngx_init_temp_number(); | |
407 | |
408 /* | |
409 * disable deleting previous events for the listening sockets because | |
410 * in the worker processes there are no events at all at this point | |
411 */ | |
412 ls = cycle->listening.elts; | |
413 for (i = 0; i < cycle->listening.nelts; i++) { | |
414 ls[i].remain = 0; | |
415 } | |
416 | |
417 for (i = 0; ngx_modules[i]; i++) { | |
418 if (ngx_modules[i]->init_process) { | |
419 if (ngx_modules[i]->init_process(cycle) == NGX_ERROR) { | |
420 /* fatal */ | |
421 exit(1); | |
422 } | |
423 } | |
424 } | |
425 | |
426 ngx_setproctitle("worker process"); | |
427 | |
428 #if (NGX_THREADS) | |
429 | |
430 if (ngx_init_threads(5, 128 * 1024 * 1024, cycle) == NGX_ERROR) { | |
431 /* fatal */ | |
432 exit(1); | |
433 } | |
434 | |
435 for (i = 0; i < 1; i++) { | |
436 if (ngx_create_thread(&tid, ngx_worker_thread_cycle, | |
437 cycle, cycle->log) != 0) | |
438 { | |
439 /* fatal */ | |
440 exit(1); | |
441 } | |
442 } | |
443 | |
444 #endif | |
445 | |
446 for ( ;; ) { | |
447 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "worker cycle"); | |
448 | |
449 ngx_process_events(cycle->log); | |
450 | |
451 if (ngx_terminate) { | |
452 ngx_log_error(NGX_LOG_INFO, cycle->log, 0, "exiting"); | |
453 exit(0); | |
454 } | |
455 | |
456 if (ngx_quit) { | |
457 ngx_log_error(NGX_LOG_INFO, cycle->log, 0, | |
458 "gracefully shutting down"); | |
459 ngx_setproctitle("worker process is shutting down"); | |
460 break; | |
461 } | |
462 | |
463 if (ngx_reopen) { | |
464 ngx_log_error(NGX_LOG_INFO, cycle->log, 0, "reopen logs"); | |
465 ngx_reopen_files(cycle, -1); | |
466 ngx_reopen = 0; | |
467 } | |
468 } | |
469 | |
470 ngx_close_listening_sockets(cycle); | |
471 | |
472 for ( ;; ) { | |
473 if (ngx_event_timer_rbtree == &ngx_event_timer_sentinel) { | |
474 ngx_log_error(NGX_LOG_INFO, cycle->log, 0, "exiting"); | |
475 exit(0); | |
476 } | |
477 | |
478 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "worker cycle"); | |
479 | |
480 ngx_process_events(cycle->log); | |
481 | |
482 if (ngx_reopen) { | |
483 ngx_log_error(NGX_LOG_INFO, cycle->log, 0, "reopen logs"); | |
484 ngx_reopen_files(cycle, -1); | |
485 ngx_reopen = 0; | |
486 } | |
487 } | |
488 } | |
489 | |
490 | |
491 #if (NGX_THREADS) | |
492 | |
493 int ngx_worker_thread_cycle(void *data) | |
494 { | |
495 ngx_cycle_t *cycle = data; | |
496 | |
497 struct timeval tv; | |
498 | |
499 /* STUB */ | |
500 | |
501 ngx_log_debug1(NGX_LOG_DEBUG_CORE, ngx_cycle->log, ngx_errno, | |
502 "thread %d started", ngx_thread_self()); | |
503 | |
504 ngx_setproctitle("worker thread"); | |
505 | |
506 sleep(5); | |
507 | |
508 ngx_gettimeofday(&tv); | |
509 ngx_time_update(tv.tv_sec); | |
510 | |
511 ngx_log_debug1(NGX_LOG_DEBUG_CORE, ngx_cycle->log, ngx_errno, | |
512 "thread %d done", ngx_thread_self()); | |
513 | |
514 return 1; | |
515 } | |
516 | |
517 #endif |