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