Mercurial > hg > nginx
comparison src/core/nginx.c @ 279:b79f021a644a
nginx-0.0.2-2004-03-04-19:34:23 import
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Thu, 04 Mar 2004 16:34:23 +0000 |
parents | 0ba4821f4460 |
children | 30310107dbc9 |
comparison
equal
deleted
inserted
replaced
278:0ba4821f4460 | 279:b79f021a644a |
---|---|
252 | 252 |
253 ngx_master_process_cycle(cycle, &ctx); | 253 ngx_master_process_cycle(cycle, &ctx); |
254 | 254 |
255 return 0; | 255 return 0; |
256 } | 256 } |
257 | |
258 | |
259 #if 0 | |
260 | |
261 /* TODO: broken NGX_PROCESS_SINGLE */ | |
262 | |
263 static void ngx_master_process_cycle(ngx_cycle_t *cycle, ngx_master_ctx_t *ctx) | |
264 { | |
265 int signo; | |
266 sigset_t set; | |
267 struct timeval tv; | |
268 struct itimerval itv; | |
269 ngx_uint_t i, live; | |
270 ngx_msec_t delay; | |
271 ngx_core_conf_t *ccf; | |
272 | |
273 sigemptyset(&set); | |
274 sigaddset(&set, SIGCHLD); | |
275 sigaddset(&set, SIGALRM); | |
276 sigaddset(&set, SIGINT); | |
277 sigaddset(&set, ngx_signal_value(NGX_RECONFIGURE_SIGNAL)); | |
278 sigaddset(&set, ngx_signal_value(NGX_REOPEN_SIGNAL)); | |
279 sigaddset(&set, ngx_signal_value(NGX_NOACCEPT_SIGNAL)); | |
280 sigaddset(&set, ngx_signal_value(NGX_TERMINATE_SIGNAL)); | |
281 sigaddset(&set, ngx_signal_value(NGX_SHUTDOWN_SIGNAL)); | |
282 sigaddset(&set, ngx_signal_value(NGX_CHANGEBIN_SIGNAL)); | |
283 | |
284 if (sigprocmask(SIG_BLOCK, &set, NULL) == -1) { | |
285 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, | |
286 "sigprocmask() failed"); | |
287 } | |
288 | |
289 sigemptyset(&set); | |
290 | |
291 ngx_setproctitle("master process"); | |
292 | |
293 ngx_new_binary = 0; | |
294 delay = 0; | |
295 signo = 0; | |
296 live = 0; | |
297 | |
298 for ( ;; ) { | |
299 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "new cycle"); | |
300 | |
301 if (ngx_process == NGX_PROCESS_MASTER) { | |
302 ngx_spawn_process(cycle, ngx_worker_process_cycle, NULL, | |
303 "worker process", NGX_PROCESS_RESPAWN); | |
304 | |
305 /* | |
306 * we have to limit the maximum life time of the worker processes | |
307 * by 1 month because our millisecond event timer is limited | |
308 * by 49 days on 32-bit platforms | |
309 */ | |
310 | |
311 itv.it_interval.tv_sec = 0; | |
312 itv.it_interval.tv_usec = 0; | |
313 itv.it_value.tv_sec = 30 * 24 * 60 * 60; | |
314 itv.it_value.tv_usec = 0; | |
315 | |
316 if (setitimer(ITIMER_REAL, &itv, NULL) == -1) { | |
317 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, | |
318 "setitimer() failed"); | |
319 } | |
320 | |
321 live = 1; | |
322 | |
323 } else { | |
324 ngx_init_temp_number(); | |
325 | |
326 for (i = 0; ngx_modules[i]; i++) { | |
327 if (ngx_modules[i]->init_process) { | |
328 if (ngx_modules[i]->init_process(cycle) == NGX_ERROR) { | |
329 /* fatal */ | |
330 exit(1); | |
331 } | |
332 } | |
333 } | |
334 } | |
335 | |
336 ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, | |
337 ngx_core_module); | |
338 | |
339 /* a cycle with the same configuration because a new one is invalid */ | |
340 | |
341 for ( ;; ) { | |
342 | |
343 /* an event loop */ | |
344 | |
345 for ( ;; ) { | |
346 | |
347 if (ngx_process == NGX_PROCESS_MASTER) { | |
348 if (delay) { | |
349 delay *= 2; | |
350 | |
351 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, | |
352 "temination cycle: %d", delay); | |
353 | |
354 itv.it_interval.tv_sec = 0; | |
355 itv.it_interval.tv_usec = 0; | |
356 itv.it_value.tv_sec = delay / 1000; | |
357 itv.it_value.tv_usec = (delay % 1000 ) * 1000; | |
358 | |
359 if (setitimer(ITIMER_REAL, &itv, NULL) == -1) { | |
360 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, | |
361 "setitimer() failed"); | |
362 } | |
363 } | |
364 | |
365 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, | |
366 "sigsuspend"); | |
367 | |
368 sigsuspend(&set); | |
369 | |
370 ngx_gettimeofday(&tv); | |
371 ngx_time_update(tv.tv_sec); | |
372 | |
373 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, | |
374 "wake up"); | |
375 | |
376 } else { /* NGX_PROCESS_SINGLE */ | |
377 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, | |
378 "worker cycle"); | |
379 | |
380 ngx_process_events(cycle->log); | |
381 live = 0; | |
382 } | |
383 | |
384 if (ngx_reap) { | |
385 ngx_reap = 0; | |
386 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, | |
387 "reap childs"); | |
388 | |
389 live = 0; | |
390 for (i = 0; i < ngx_last_process; i++) { | |
391 | |
392 ngx_log_debug5(NGX_LOG_DEBUG_EVENT, cycle->log, 0, | |
393 "child: " PID_T_FMT | |
394 " e:%d t:%d d:%d r:%d", | |
395 ngx_processes[i].pid, | |
396 ngx_processes[i].exiting, | |
397 ngx_processes[i].exited, | |
398 ngx_processes[i].detached, | |
399 ngx_processes[i].respawn); | |
400 | |
401 if (ngx_processes[i].exited) { | |
402 | |
403 if (ngx_processes[i].respawn | |
404 && !ngx_processes[i].exiting | |
405 && !ngx_terminate | |
406 && !ngx_quit) | |
407 { | |
408 if (ngx_spawn_process(cycle, | |
409 ngx_processes[i].proc, | |
410 ngx_processes[i].data, | |
411 ngx_processes[i].name, i) | |
412 == NGX_ERROR) | |
413 { | |
414 ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, | |
415 "can not respawn %s", | |
416 ngx_processes[i].name); | |
417 continue; | |
418 } | |
419 | |
420 live = 1; | |
421 | |
422 continue; | |
423 } | |
424 | |
425 if (ngx_processes[i].pid == ngx_new_binary) { | |
426 ngx_new_binary = 0; | |
427 | |
428 /* TODO: if (ngx_noaccept) ngx_configure = 1 */ | |
429 } | |
430 | |
431 if (i != --ngx_last_process) { | |
432 ngx_processes[i--] = | |
433 ngx_processes[ngx_last_process]; | |
434 } | |
435 | |
436 } else if (ngx_processes[i].exiting | |
437 || !ngx_processes[i].detached) | |
438 { | |
439 live = 1; | |
440 } | |
441 } | |
442 } | |
443 | |
444 if (!live && (ngx_terminate || ngx_quit)) { | |
445 ngx_master_exit(cycle, ctx); | |
446 } | |
447 | |
448 if (ngx_terminate) { | |
449 if (delay == 0) { | |
450 delay = 50; | |
451 } | |
452 | |
453 if (delay > 1000) { | |
454 signo = SIGKILL; | |
455 } else { | |
456 signo = ngx_signal_value(NGX_TERMINATE_SIGNAL); | |
457 } | |
458 | |
459 } else if (ngx_quit) { | |
460 signo = ngx_signal_value(NGX_SHUTDOWN_SIGNAL); | |
461 | |
462 } else if (ngx_timer) { | |
463 signo = ngx_signal_value(NGX_SHUTDOWN_SIGNAL); | |
464 | |
465 } else { | |
466 | |
467 if (ngx_noaccept) { | |
468 signo = ngx_signal_value(NGX_SHUTDOWN_SIGNAL); | |
469 } | |
470 | |
471 if (ngx_change_binary) { | |
472 ngx_change_binary = 0; | |
473 ngx_log_error(NGX_LOG_INFO, cycle->log, 0, | |
474 "changing binary"); | |
475 ngx_new_binary = ngx_exec_new_binary(cycle, ctx->argv); | |
476 } | |
477 | |
478 if (ngx_reconfigure) { | |
479 signo = ngx_signal_value(NGX_SHUTDOWN_SIGNAL); | |
480 ngx_log_error(NGX_LOG_INFO, cycle->log, 0, | |
481 "reconfiguring"); | |
482 } | |
483 | |
484 if (ngx_reopen) { | |
485 if (ngx_process == NGX_PROCESS_MASTER) { | |
486 if (ccf->worker_reopen != 0) { | |
487 signo = ngx_signal_value(NGX_REOPEN_SIGNAL); | |
488 ngx_reopen = 0; | |
489 | |
490 } else if (ngx_noaccept) { | |
491 ngx_reopen = 0; | |
492 | |
493 } else { | |
494 signo = ngx_signal_value(NGX_SHUTDOWN_SIGNAL); | |
495 } | |
496 | |
497 } else { /* NGX_PROCESS_SINGLE */ | |
498 ngx_reopen = 0; | |
499 } | |
500 | |
501 ngx_log_error(NGX_LOG_INFO, cycle->log, 0, | |
502 "reopening logs"); | |
503 ngx_reopen_files(cycle, | |
504 ccf->worker_reopen != 0 ? ccf->user : (uid_t) -1); | |
505 } | |
506 } | |
507 | |
508 if (signo) { | |
509 for (i = 0; i < ngx_last_process; i++) { | |
510 | |
511 if (ngx_processes[i].detached) { | |
512 continue; | |
513 } | |
514 | |
515 ngx_log_debug2(NGX_LOG_DEBUG_CORE, cycle->log, 0, | |
516 "kill (" PID_T_FMT ", %d)" , | |
517 ngx_processes[i].pid, signo); | |
518 | |
519 if (kill(ngx_processes[i].pid, signo) == -1) { | |
520 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, | |
521 "kill(%d, %d) failed", | |
522 ngx_processes[i].pid, signo); | |
523 continue; | |
524 } | |
525 | |
526 if (signo != ngx_signal_value(NGX_REOPEN_SIGNAL)) { | |
527 ngx_processes[i].exiting = 1; | |
528 } | |
529 } | |
530 | |
531 signo = 0; | |
532 } | |
533 | |
534 if (ngx_reopen || ngx_reconfigure || ngx_timer) { | |
535 break; | |
536 } | |
537 } | |
538 | |
539 if (ngx_reopen) { | |
540 ngx_reopen = 0; | |
541 | |
542 } else if (ngx_timer) { | |
543 ngx_timer = 0; | |
544 | |
545 } else if (ngx_noaccept) { | |
546 ngx_noaccept = 0; | |
547 ngx_reconfigure = 0; | |
548 | |
549 } else { | |
550 cycle = ngx_init_cycle(cycle); | |
551 if (cycle == NULL) { | |
552 cycle = (ngx_cycle_t *) ngx_cycle; | |
553 continue; | |
554 } | |
555 | |
556 ngx_cycle = cycle; | |
557 ngx_reconfigure = 0; | |
558 } | |
559 | |
560 break; | |
561 } | |
562 } | |
563 } | |
564 | |
565 | |
566 static void ngx_master_exit(ngx_cycle_t *cycle, ngx_master_ctx_t *ctx) | |
567 { | |
568 char *name; | |
569 | |
570 if (ngx_inherited && getppid() > 1) { | |
571 name = ctx->pid.name.data; | |
572 | |
573 } else { | |
574 name = ctx->name; | |
575 } | |
576 | |
577 if (ngx_delete_file(name) == NGX_FILE_ERROR) { | |
578 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, | |
579 ngx_delete_file_n " \"%s\" failed", name); | |
580 } | |
581 | |
582 ngx_log_error(NGX_LOG_INFO, cycle->log, 0, "exit"); | |
583 exit(0); | |
584 } | |
585 | |
586 | |
587 static void ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data) | |
588 { | |
589 sigset_t set; | |
590 ngx_int_t i; | |
591 ngx_listening_t *ls; | |
592 ngx_core_conf_t *ccf; | |
593 #if (NGX_THREADS) | |
594 ngx_tid_t tid; | |
595 #endif | |
596 | |
597 ngx_process = NGX_PROCESS_WORKER; | |
598 ngx_last_process = 0; | |
599 | |
600 ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); | |
601 | |
602 if (ccf->group != (gid_t) NGX_CONF_UNSET) { | |
603 if (setuid(ccf->group) == -1) { | |
604 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, | |
605 "setgid(%d) failed", ccf->group); | |
606 /* fatal */ | |
607 exit(2); | |
608 } | |
609 } | |
610 | |
611 if (ccf->user != (uid_t) NGX_CONF_UNSET && geteuid() == 0) { | |
612 if (setuid(ccf->user) == -1) { | |
613 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, | |
614 "setuid(%d) failed", ccf->user); | |
615 /* fatal */ | |
616 exit(2); | |
617 } | |
618 } | |
619 | |
620 #if (HAVE_PR_SET_DUMPABLE) | |
621 | |
622 /* allow coredump after setuid() in Linux 2.4.x */ | |
623 | |
624 if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) == -1) { | |
625 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, | |
626 "prctl(PR_SET_DUMPABLE) failed"); | |
627 } | |
628 | |
629 #endif | |
630 | |
631 sigemptyset(&set); | |
632 | |
633 if (sigprocmask(SIG_SETMASK, &set, NULL) == -1) { | |
634 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, | |
635 "sigprocmask() failed"); | |
636 } | |
637 | |
638 ngx_init_temp_number(); | |
639 | |
640 /* | |
641 * disable deleting previous events for the listening sockets because | |
642 * in the worker processes there are no events at all at this point | |
643 */ | |
644 ls = cycle->listening.elts; | |
645 for (i = 0; i < cycle->listening.nelts; i++) { | |
646 ls[i].remain = 0; | |
647 } | |
648 | |
649 for (i = 0; ngx_modules[i]; i++) { | |
650 if (ngx_modules[i]->init_process) { | |
651 if (ngx_modules[i]->init_process(cycle) == NGX_ERROR) { | |
652 /* fatal */ | |
653 exit(1); | |
654 } | |
655 } | |
656 } | |
657 | |
658 ngx_setproctitle("worker process"); | |
659 | |
660 #if (NGX_THREADS) | |
661 | |
662 if (ngx_init_threads(5, 128 * 1024 * 1024, cycle) == NGX_ERROR) { | |
663 /* fatal */ | |
664 exit(1); | |
665 } | |
666 | |
667 for (i = 0; i < 1; i++) { | |
668 if (ngx_create_thread(&tid, ngx_worker_thread_cycle, | |
669 cycle, cycle->log) != 0) | |
670 { | |
671 /* fatal */ | |
672 exit(1); | |
673 } | |
674 } | |
675 | |
676 #endif | |
677 | |
678 for ( ;; ) { | |
679 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "worker cycle"); | |
680 | |
681 ngx_process_events(cycle->log); | |
682 | |
683 if (ngx_terminate) { | |
684 ngx_log_error(NGX_LOG_INFO, cycle->log, 0, "exiting"); | |
685 exit(0); | |
686 } | |
687 | |
688 if (ngx_quit) { | |
689 ngx_log_error(NGX_LOG_INFO, cycle->log, 0, | |
690 "gracefully shutting down"); | |
691 ngx_setproctitle("worker process is shutting down"); | |
692 break; | |
693 } | |
694 | |
695 if (ngx_reopen) { | |
696 ngx_log_error(NGX_LOG_INFO, cycle->log, 0, "reopen logs"); | |
697 ngx_reopen_files(cycle, -1); | |
698 ngx_reopen = 0; | |
699 } | |
700 } | |
701 | |
702 ngx_close_listening_sockets(cycle); | |
703 | |
704 for ( ;; ) { | |
705 if (ngx_event_timer_rbtree == &ngx_event_timer_sentinel) { | |
706 ngx_log_error(NGX_LOG_INFO, cycle->log, 0, "exiting"); | |
707 exit(0); | |
708 } | |
709 | |
710 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "worker cycle"); | |
711 | |
712 ngx_process_events(cycle->log); | |
713 | |
714 if (ngx_reopen) { | |
715 ngx_log_error(NGX_LOG_INFO, cycle->log, 0, "reopen logs"); | |
716 ngx_reopen_files(cycle, -1); | |
717 ngx_reopen = 0; | |
718 } | |
719 } | |
720 } | |
721 | |
722 | |
723 #if (NGX_THREADS) | |
724 | |
725 int ngx_worker_thread_cycle(void *data) | |
726 { | |
727 ngx_cycle_t *cycle = data; | |
728 | |
729 struct timeval tv; | |
730 | |
731 /* STUB */ | |
732 | |
733 ngx_log_debug1(NGX_LOG_DEBUG_CORE, ngx_cycle->log, ngx_errno, | |
734 "thread %d started", ngx_thread_self()); | |
735 | |
736 ngx_setproctitle("worker thread"); | |
737 | |
738 sleep(5); | |
739 | |
740 ngx_gettimeofday(&tv); | |
741 ngx_time_update(tv.tv_sec); | |
742 | |
743 ngx_log_debug1(NGX_LOG_DEBUG_CORE, ngx_cycle->log, ngx_errno, | |
744 "thread %d done", ngx_thread_self()); | |
745 | |
746 return 1; | |
747 } | |
748 | |
749 #endif | |
750 | |
751 #endif | |
752 | 257 |
753 | 258 |
754 static ngx_int_t ngx_add_inherited_sockets(ngx_cycle_t *cycle, char **envp) | 259 static ngx_int_t ngx_add_inherited_sockets(ngx_cycle_t *cycle, char **envp) |
755 { | 260 { |
756 char *p, *v; | 261 char *p, *v; |
822 | 327 |
823 env[0] = var; | 328 env[0] = var; |
824 env[1] = NULL; | 329 env[1] = NULL; |
825 ctx.envp = (char *const *) &env; | 330 ctx.envp = (char *const *) &env; |
826 | 331 |
827 pid = ngx_exec(cycle, &ctx); | 332 pid = ngx_execute(cycle, &ctx); |
828 | 333 |
829 ngx_free(var); | 334 ngx_free(var); |
830 | 335 |
831 return pid; | 336 return pid; |
832 } | 337 } |