Annotation of embedaddon/nginx/src/os/unix/ngx_process_cycle.c, revision 1.1

1.1     ! misho       1: 
        !             2: /*
        !             3:  * Copyright (C) Igor Sysoev
        !             4:  * Copyright (C) Nginx, Inc.
        !             5:  */
        !             6: 
        !             7: 
        !             8: #include <ngx_config.h>
        !             9: #include <ngx_core.h>
        !            10: #include <ngx_event.h>
        !            11: #include <ngx_channel.h>
        !            12: 
        !            13: 
        !            14: static void ngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t n,
        !            15:     ngx_int_t type);
        !            16: static void ngx_start_cache_manager_processes(ngx_cycle_t *cycle,
        !            17:     ngx_uint_t respawn);
        !            18: static void ngx_pass_open_channel(ngx_cycle_t *cycle, ngx_channel_t *ch);
        !            19: static void ngx_signal_worker_processes(ngx_cycle_t *cycle, int signo);
        !            20: static ngx_uint_t ngx_reap_children(ngx_cycle_t *cycle);
        !            21: static void ngx_master_process_exit(ngx_cycle_t *cycle);
        !            22: static void ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data);
        !            23: static void ngx_worker_process_init(ngx_cycle_t *cycle, ngx_int_t worker);
        !            24: static void ngx_worker_process_exit(ngx_cycle_t *cycle);
        !            25: static void ngx_channel_handler(ngx_event_t *ev);
        !            26: #if (NGX_THREADS)
        !            27: static void ngx_wakeup_worker_threads(ngx_cycle_t *cycle);
        !            28: static ngx_thread_value_t ngx_worker_thread_cycle(void *data);
        !            29: #endif
        !            30: static void ngx_cache_manager_process_cycle(ngx_cycle_t *cycle, void *data);
        !            31: static void ngx_cache_manager_process_handler(ngx_event_t *ev);
        !            32: static void ngx_cache_loader_process_handler(ngx_event_t *ev);
        !            33: 
        !            34: 
        !            35: ngx_uint_t    ngx_process;
        !            36: ngx_pid_t     ngx_pid;
        !            37: ngx_uint_t    ngx_threaded;
        !            38: 
        !            39: sig_atomic_t  ngx_reap;
        !            40: sig_atomic_t  ngx_sigio;
        !            41: sig_atomic_t  ngx_sigalrm;
        !            42: sig_atomic_t  ngx_terminate;
        !            43: sig_atomic_t  ngx_quit;
        !            44: sig_atomic_t  ngx_debug_quit;
        !            45: ngx_uint_t    ngx_exiting;
        !            46: sig_atomic_t  ngx_reconfigure;
        !            47: sig_atomic_t  ngx_reopen;
        !            48: 
        !            49: sig_atomic_t  ngx_change_binary;
        !            50: ngx_pid_t     ngx_new_binary;
        !            51: ngx_uint_t    ngx_inherited;
        !            52: ngx_uint_t    ngx_daemonized;
        !            53: 
        !            54: sig_atomic_t  ngx_noaccept;
        !            55: ngx_uint_t    ngx_noaccepting;
        !            56: ngx_uint_t    ngx_restart;
        !            57: 
        !            58: 
        !            59: #if (NGX_THREADS)
        !            60: volatile ngx_thread_t  ngx_threads[NGX_MAX_THREADS];
        !            61: ngx_int_t              ngx_threads_n;
        !            62: #endif
        !            63: 
        !            64: 
        !            65: static u_char  master_process[] = "master process";
        !            66: 
        !            67: 
        !            68: static ngx_cache_manager_ctx_t  ngx_cache_manager_ctx = {
        !            69:     ngx_cache_manager_process_handler, "cache manager process", 0
        !            70: };
        !            71: 
        !            72: static ngx_cache_manager_ctx_t  ngx_cache_loader_ctx = {
        !            73:     ngx_cache_loader_process_handler, "cache loader process", 60000
        !            74: };
        !            75: 
        !            76: 
        !            77: static ngx_cycle_t      ngx_exit_cycle;
        !            78: static ngx_log_t        ngx_exit_log;
        !            79: static ngx_open_file_t  ngx_exit_log_file;
        !            80: 
        !            81: 
        !            82: void
        !            83: ngx_master_process_cycle(ngx_cycle_t *cycle)
        !            84: {
        !            85:     char              *title;
        !            86:     u_char            *p;
        !            87:     size_t             size;
        !            88:     ngx_int_t          i;
        !            89:     ngx_uint_t         n, sigio;
        !            90:     sigset_t           set;
        !            91:     struct itimerval   itv;
        !            92:     ngx_uint_t         live;
        !            93:     ngx_msec_t         delay;
        !            94:     ngx_listening_t   *ls;
        !            95:     ngx_core_conf_t   *ccf;
        !            96: 
        !            97:     sigemptyset(&set);
        !            98:     sigaddset(&set, SIGCHLD);
        !            99:     sigaddset(&set, SIGALRM);
        !           100:     sigaddset(&set, SIGIO);
        !           101:     sigaddset(&set, SIGINT);
        !           102:     sigaddset(&set, ngx_signal_value(NGX_RECONFIGURE_SIGNAL));
        !           103:     sigaddset(&set, ngx_signal_value(NGX_REOPEN_SIGNAL));
        !           104:     sigaddset(&set, ngx_signal_value(NGX_NOACCEPT_SIGNAL));
        !           105:     sigaddset(&set, ngx_signal_value(NGX_TERMINATE_SIGNAL));
        !           106:     sigaddset(&set, ngx_signal_value(NGX_SHUTDOWN_SIGNAL));
        !           107:     sigaddset(&set, ngx_signal_value(NGX_CHANGEBIN_SIGNAL));
        !           108: 
        !           109:     if (sigprocmask(SIG_BLOCK, &set, NULL) == -1) {
        !           110:         ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
        !           111:                       "sigprocmask() failed");
        !           112:     }
        !           113: 
        !           114:     sigemptyset(&set);
        !           115: 
        !           116: 
        !           117:     size = sizeof(master_process);
        !           118: 
        !           119:     for (i = 0; i < ngx_argc; i++) {
        !           120:         size += ngx_strlen(ngx_argv[i]) + 1;
        !           121:     }
        !           122: 
        !           123:     title = ngx_pnalloc(cycle->pool, size);
        !           124: 
        !           125:     p = ngx_cpymem(title, master_process, sizeof(master_process) - 1);
        !           126:     for (i = 0; i < ngx_argc; i++) {
        !           127:         *p++ = ' ';
        !           128:         p = ngx_cpystrn(p, (u_char *) ngx_argv[i], size);
        !           129:     }
        !           130: 
        !           131:     ngx_setproctitle(title);
        !           132: 
        !           133: 
        !           134:     ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
        !           135: 
        !           136:     ngx_start_worker_processes(cycle, ccf->worker_processes,
        !           137:                                NGX_PROCESS_RESPAWN);
        !           138:     ngx_start_cache_manager_processes(cycle, 0);
        !           139: 
        !           140:     ngx_new_binary = 0;
        !           141:     delay = 0;
        !           142:     sigio = 0;
        !           143:     live = 1;
        !           144: 
        !           145:     for ( ;; ) {
        !           146:         if (delay) {
        !           147:             if (ngx_sigalrm) {
        !           148:                 sigio = 0;
        !           149:                 delay *= 2;
        !           150:                 ngx_sigalrm = 0;
        !           151:             }
        !           152: 
        !           153:             ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
        !           154:                            "termination cycle: %d", delay);
        !           155: 
        !           156:             itv.it_interval.tv_sec = 0;
        !           157:             itv.it_interval.tv_usec = 0;
        !           158:             itv.it_value.tv_sec = delay / 1000;
        !           159:             itv.it_value.tv_usec = (delay % 1000 ) * 1000;
        !           160: 
        !           161:             if (setitimer(ITIMER_REAL, &itv, NULL) == -1) {
        !           162:                 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
        !           163:                               "setitimer() failed");
        !           164:             }
        !           165:         }
        !           166: 
        !           167:         ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "sigsuspend");
        !           168: 
        !           169:         sigsuspend(&set);
        !           170: 
        !           171:         ngx_time_update();
        !           172: 
        !           173:         ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
        !           174:                        "wake up, sigio %i", sigio);
        !           175: 
        !           176:         if (ngx_reap) {
        !           177:             ngx_reap = 0;
        !           178:             ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "reap children");
        !           179: 
        !           180:             live = ngx_reap_children(cycle);
        !           181:         }
        !           182: 
        !           183:         if (!live && (ngx_terminate || ngx_quit)) {
        !           184:             ngx_master_process_exit(cycle);
        !           185:         }
        !           186: 
        !           187:         if (ngx_terminate) {
        !           188:             if (delay == 0) {
        !           189:                 delay = 50;
        !           190:             }
        !           191: 
        !           192:             if (sigio) {
        !           193:                 sigio--;
        !           194:                 continue;
        !           195:             }
        !           196: 
        !           197:             sigio = ccf->worker_processes + 2 /* cache processes */;
        !           198: 
        !           199:             if (delay > 1000) {
        !           200:                 ngx_signal_worker_processes(cycle, SIGKILL);
        !           201:             } else {
        !           202:                 ngx_signal_worker_processes(cycle,
        !           203:                                        ngx_signal_value(NGX_TERMINATE_SIGNAL));
        !           204:             }
        !           205: 
        !           206:             continue;
        !           207:         }
        !           208: 
        !           209:         if (ngx_quit) {
        !           210:             ngx_signal_worker_processes(cycle,
        !           211:                                         ngx_signal_value(NGX_SHUTDOWN_SIGNAL));
        !           212: 
        !           213:             ls = cycle->listening.elts;
        !           214:             for (n = 0; n < cycle->listening.nelts; n++) {
        !           215:                 if (ngx_close_socket(ls[n].fd) == -1) {
        !           216:                     ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno,
        !           217:                                   ngx_close_socket_n " %V failed",
        !           218:                                   &ls[n].addr_text);
        !           219:                 }
        !           220:             }
        !           221:             cycle->listening.nelts = 0;
        !           222: 
        !           223:             continue;
        !           224:         }
        !           225: 
        !           226:         if (ngx_reconfigure) {
        !           227:             ngx_reconfigure = 0;
        !           228: 
        !           229:             if (ngx_new_binary) {
        !           230:                 ngx_start_worker_processes(cycle, ccf->worker_processes,
        !           231:                                            NGX_PROCESS_RESPAWN);
        !           232:                 ngx_start_cache_manager_processes(cycle, 0);
        !           233:                 ngx_noaccepting = 0;
        !           234: 
        !           235:                 continue;
        !           236:             }
        !           237: 
        !           238:             ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reconfiguring");
        !           239: 
        !           240:             cycle = ngx_init_cycle(cycle);
        !           241:             if (cycle == NULL) {
        !           242:                 cycle = (ngx_cycle_t *) ngx_cycle;
        !           243:                 continue;
        !           244:             }
        !           245: 
        !           246:             ngx_cycle = cycle;
        !           247:             ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx,
        !           248:                                                    ngx_core_module);
        !           249:             ngx_start_worker_processes(cycle, ccf->worker_processes,
        !           250:                                        NGX_PROCESS_JUST_RESPAWN);
        !           251:             ngx_start_cache_manager_processes(cycle, 1);
        !           252: 
        !           253:             /* allow new processes to start */
        !           254:             ngx_msleep(100);
        !           255: 
        !           256:             live = 1;
        !           257:             ngx_signal_worker_processes(cycle,
        !           258:                                         ngx_signal_value(NGX_SHUTDOWN_SIGNAL));
        !           259:         }
        !           260: 
        !           261:         if (ngx_restart) {
        !           262:             ngx_restart = 0;
        !           263:             ngx_start_worker_processes(cycle, ccf->worker_processes,
        !           264:                                        NGX_PROCESS_RESPAWN);
        !           265:             ngx_start_cache_manager_processes(cycle, 0);
        !           266:             live = 1;
        !           267:         }
        !           268: 
        !           269:         if (ngx_reopen) {
        !           270:             ngx_reopen = 0;
        !           271:             ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reopening logs");
        !           272:             ngx_reopen_files(cycle, ccf->user);
        !           273:             ngx_signal_worker_processes(cycle,
        !           274:                                         ngx_signal_value(NGX_REOPEN_SIGNAL));
        !           275:         }
        !           276: 
        !           277:         if (ngx_change_binary) {
        !           278:             ngx_change_binary = 0;
        !           279:             ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "changing binary");
        !           280:             ngx_new_binary = ngx_exec_new_binary(cycle, ngx_argv);
        !           281:         }
        !           282: 
        !           283:         if (ngx_noaccept) {
        !           284:             ngx_noaccept = 0;
        !           285:             ngx_noaccepting = 1;
        !           286:             ngx_signal_worker_processes(cycle,
        !           287:                                         ngx_signal_value(NGX_SHUTDOWN_SIGNAL));
        !           288:         }
        !           289:     }
        !           290: }
        !           291: 
        !           292: 
        !           293: void
        !           294: ngx_single_process_cycle(ngx_cycle_t *cycle)
        !           295: {
        !           296:     ngx_uint_t  i;
        !           297: 
        !           298:     if (ngx_set_environment(cycle, NULL) == NULL) {
        !           299:         /* fatal */
        !           300:         exit(2);
        !           301:     }
        !           302: 
        !           303:     for (i = 0; ngx_modules[i]; i++) {
        !           304:         if (ngx_modules[i]->init_process) {
        !           305:             if (ngx_modules[i]->init_process(cycle) == NGX_ERROR) {
        !           306:                 /* fatal */
        !           307:                 exit(2);
        !           308:             }
        !           309:         }
        !           310:     }
        !           311: 
        !           312:     for ( ;; ) {
        !           313:         ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "worker cycle");
        !           314: 
        !           315:         ngx_process_events_and_timers(cycle);
        !           316: 
        !           317:         if (ngx_terminate || ngx_quit) {
        !           318: 
        !           319:             for (i = 0; ngx_modules[i]; i++) {
        !           320:                 if (ngx_modules[i]->exit_process) {
        !           321:                     ngx_modules[i]->exit_process(cycle);
        !           322:                 }
        !           323:             }
        !           324: 
        !           325:             ngx_master_process_exit(cycle);
        !           326:         }
        !           327: 
        !           328:         if (ngx_reconfigure) {
        !           329:             ngx_reconfigure = 0;
        !           330:             ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reconfiguring");
        !           331: 
        !           332:             cycle = ngx_init_cycle(cycle);
        !           333:             if (cycle == NULL) {
        !           334:                 cycle = (ngx_cycle_t *) ngx_cycle;
        !           335:                 continue;
        !           336:             }
        !           337: 
        !           338:             ngx_cycle = cycle;
        !           339:         }
        !           340: 
        !           341:         if (ngx_reopen) {
        !           342:             ngx_reopen = 0;
        !           343:             ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reopening logs");
        !           344:             ngx_reopen_files(cycle, (ngx_uid_t) -1);
        !           345:         }
        !           346:     }
        !           347: }
        !           348: 
        !           349: 
        !           350: static void
        !           351: ngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t n, ngx_int_t type)
        !           352: {
        !           353:     ngx_int_t      i;
        !           354:     ngx_channel_t  ch;
        !           355: 
        !           356:     ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "start worker processes");
        !           357: 
        !           358:     ch.command = NGX_CMD_OPEN_CHANNEL;
        !           359: 
        !           360:     for (i = 0; i < n; i++) {
        !           361: 
        !           362:         ngx_spawn_process(cycle, ngx_worker_process_cycle,
        !           363:                           (void *) (intptr_t) i, "worker process", type);
        !           364: 
        !           365:         ch.pid = ngx_processes[ngx_process_slot].pid;
        !           366:         ch.slot = ngx_process_slot;
        !           367:         ch.fd = ngx_processes[ngx_process_slot].channel[0];
        !           368: 
        !           369:         ngx_pass_open_channel(cycle, &ch);
        !           370:     }
        !           371: }
        !           372: 
        !           373: 
        !           374: static void
        !           375: ngx_start_cache_manager_processes(ngx_cycle_t *cycle, ngx_uint_t respawn)
        !           376: {
        !           377:     ngx_uint_t       i, manager, loader;
        !           378:     ngx_path_t     **path;
        !           379:     ngx_channel_t    ch;
        !           380: 
        !           381:     manager = 0;
        !           382:     loader = 0;
        !           383: 
        !           384:     path = ngx_cycle->paths.elts;
        !           385:     for (i = 0; i < ngx_cycle->paths.nelts; i++) {
        !           386: 
        !           387:         if (path[i]->manager) {
        !           388:             manager = 1;
        !           389:         }
        !           390: 
        !           391:         if (path[i]->loader) {
        !           392:             loader = 1;
        !           393:         }
        !           394:     }
        !           395: 
        !           396:     if (manager == 0) {
        !           397:         return;
        !           398:     }
        !           399: 
        !           400:     ngx_spawn_process(cycle, ngx_cache_manager_process_cycle,
        !           401:                       &ngx_cache_manager_ctx, "cache manager process",
        !           402:                       respawn ? NGX_PROCESS_JUST_RESPAWN : NGX_PROCESS_RESPAWN);
        !           403: 
        !           404:     ch.command = NGX_CMD_OPEN_CHANNEL;
        !           405:     ch.pid = ngx_processes[ngx_process_slot].pid;
        !           406:     ch.slot = ngx_process_slot;
        !           407:     ch.fd = ngx_processes[ngx_process_slot].channel[0];
        !           408: 
        !           409:     ngx_pass_open_channel(cycle, &ch);
        !           410: 
        !           411:     if (loader == 0) {
        !           412:         return;
        !           413:     }
        !           414: 
        !           415:     ngx_spawn_process(cycle, ngx_cache_manager_process_cycle,
        !           416:                       &ngx_cache_loader_ctx, "cache loader process",
        !           417:                       respawn ? NGX_PROCESS_JUST_SPAWN : NGX_PROCESS_NORESPAWN);
        !           418: 
        !           419:     ch.command = NGX_CMD_OPEN_CHANNEL;
        !           420:     ch.pid = ngx_processes[ngx_process_slot].pid;
        !           421:     ch.slot = ngx_process_slot;
        !           422:     ch.fd = ngx_processes[ngx_process_slot].channel[0];
        !           423: 
        !           424:     ngx_pass_open_channel(cycle, &ch);
        !           425: }
        !           426: 
        !           427: 
        !           428: static void
        !           429: ngx_pass_open_channel(ngx_cycle_t *cycle, ngx_channel_t *ch)
        !           430: {
        !           431:     ngx_int_t  i;
        !           432: 
        !           433:     for (i = 0; i < ngx_last_process; i++) {
        !           434: 
        !           435:         if (i == ngx_process_slot
        !           436:             || ngx_processes[i].pid == -1
        !           437:             || ngx_processes[i].channel[0] == -1)
        !           438:         {
        !           439:             continue;
        !           440:         }
        !           441: 
        !           442:         ngx_log_debug6(NGX_LOG_DEBUG_CORE, cycle->log, 0,
        !           443:                       "pass channel s:%d pid:%P fd:%d to s:%i pid:%P fd:%d",
        !           444:                       ch->slot, ch->pid, ch->fd,
        !           445:                       i, ngx_processes[i].pid,
        !           446:                       ngx_processes[i].channel[0]);
        !           447: 
        !           448:         /* TODO: NGX_AGAIN */
        !           449: 
        !           450:         ngx_write_channel(ngx_processes[i].channel[0],
        !           451:                           ch, sizeof(ngx_channel_t), cycle->log);
        !           452:     }
        !           453: }
        !           454: 
        !           455: 
        !           456: static void
        !           457: ngx_signal_worker_processes(ngx_cycle_t *cycle, int signo)
        !           458: {
        !           459:     ngx_int_t      i;
        !           460:     ngx_err_t      err;
        !           461:     ngx_channel_t  ch;
        !           462: 
        !           463: #if (NGX_BROKEN_SCM_RIGHTS)
        !           464: 
        !           465:     ch.command = 0;
        !           466: 
        !           467: #else
        !           468: 
        !           469:     switch (signo) {
        !           470: 
        !           471:     case ngx_signal_value(NGX_SHUTDOWN_SIGNAL):
        !           472:         ch.command = NGX_CMD_QUIT;
        !           473:         break;
        !           474: 
        !           475:     case ngx_signal_value(NGX_TERMINATE_SIGNAL):
        !           476:         ch.command = NGX_CMD_TERMINATE;
        !           477:         break;
        !           478: 
        !           479:     case ngx_signal_value(NGX_REOPEN_SIGNAL):
        !           480:         ch.command = NGX_CMD_REOPEN;
        !           481:         break;
        !           482: 
        !           483:     default:
        !           484:         ch.command = 0;
        !           485:     }
        !           486: 
        !           487: #endif
        !           488: 
        !           489:     ch.fd = -1;
        !           490: 
        !           491: 
        !           492:     for (i = 0; i < ngx_last_process; i++) {
        !           493: 
        !           494:         ngx_log_debug7(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
        !           495:                        "child: %d %P e:%d t:%d d:%d r:%d j:%d",
        !           496:                        i,
        !           497:                        ngx_processes[i].pid,
        !           498:                        ngx_processes[i].exiting,
        !           499:                        ngx_processes[i].exited,
        !           500:                        ngx_processes[i].detached,
        !           501:                        ngx_processes[i].respawn,
        !           502:                        ngx_processes[i].just_spawn);
        !           503: 
        !           504:         if (ngx_processes[i].detached || ngx_processes[i].pid == -1) {
        !           505:             continue;
        !           506:         }
        !           507: 
        !           508:         if (ngx_processes[i].just_spawn) {
        !           509:             ngx_processes[i].just_spawn = 0;
        !           510:             continue;
        !           511:         }
        !           512: 
        !           513:         if (ngx_processes[i].exiting
        !           514:             && signo == ngx_signal_value(NGX_SHUTDOWN_SIGNAL))
        !           515:         {
        !           516:             continue;
        !           517:         }
        !           518: 
        !           519:         if (ch.command) {
        !           520:             if (ngx_write_channel(ngx_processes[i].channel[0],
        !           521:                                   &ch, sizeof(ngx_channel_t), cycle->log)
        !           522:                 == NGX_OK)
        !           523:             {
        !           524:                 if (signo != ngx_signal_value(NGX_REOPEN_SIGNAL)) {
        !           525:                     ngx_processes[i].exiting = 1;
        !           526:                 }
        !           527: 
        !           528:                 continue;
        !           529:             }
        !           530:         }
        !           531: 
        !           532:         ngx_log_debug2(NGX_LOG_DEBUG_CORE, cycle->log, 0,
        !           533:                        "kill (%P, %d)" , ngx_processes[i].pid, signo);
        !           534: 
        !           535:         if (kill(ngx_processes[i].pid, signo) == -1) {
        !           536:             err = ngx_errno;
        !           537:             ngx_log_error(NGX_LOG_ALERT, cycle->log, err,
        !           538:                           "kill(%P, %d) failed", ngx_processes[i].pid, signo);
        !           539: 
        !           540:             if (err == NGX_ESRCH) {
        !           541:                 ngx_processes[i].exited = 1;
        !           542:                 ngx_processes[i].exiting = 0;
        !           543:                 ngx_reap = 1;
        !           544:             }
        !           545: 
        !           546:             continue;
        !           547:         }
        !           548: 
        !           549:         if (signo != ngx_signal_value(NGX_REOPEN_SIGNAL)) {
        !           550:             ngx_processes[i].exiting = 1;
        !           551:         }
        !           552:     }
        !           553: }
        !           554: 
        !           555: 
        !           556: static ngx_uint_t
        !           557: ngx_reap_children(ngx_cycle_t *cycle)
        !           558: {
        !           559:     ngx_int_t         i, n;
        !           560:     ngx_uint_t        live;
        !           561:     ngx_channel_t     ch;
        !           562:     ngx_core_conf_t  *ccf;
        !           563: 
        !           564:     ch.command = NGX_CMD_CLOSE_CHANNEL;
        !           565:     ch.fd = -1;
        !           566: 
        !           567:     live = 0;
        !           568:     for (i = 0; i < ngx_last_process; i++) {
        !           569: 
        !           570:         ngx_log_debug7(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
        !           571:                        "child: %d %P e:%d t:%d d:%d r:%d j:%d",
        !           572:                        i,
        !           573:                        ngx_processes[i].pid,
        !           574:                        ngx_processes[i].exiting,
        !           575:                        ngx_processes[i].exited,
        !           576:                        ngx_processes[i].detached,
        !           577:                        ngx_processes[i].respawn,
        !           578:                        ngx_processes[i].just_spawn);
        !           579: 
        !           580:         if (ngx_processes[i].pid == -1) {
        !           581:             continue;
        !           582:         }
        !           583: 
        !           584:         if (ngx_processes[i].exited) {
        !           585: 
        !           586:             if (!ngx_processes[i].detached) {
        !           587:                 ngx_close_channel(ngx_processes[i].channel, cycle->log);
        !           588: 
        !           589:                 ngx_processes[i].channel[0] = -1;
        !           590:                 ngx_processes[i].channel[1] = -1;
        !           591: 
        !           592:                 ch.pid = ngx_processes[i].pid;
        !           593:                 ch.slot = i;
        !           594: 
        !           595:                 for (n = 0; n < ngx_last_process; n++) {
        !           596:                     if (ngx_processes[n].exited
        !           597:                         || ngx_processes[n].pid == -1
        !           598:                         || ngx_processes[n].channel[0] == -1)
        !           599:                     {
        !           600:                         continue;
        !           601:                     }
        !           602: 
        !           603:                     ngx_log_debug3(NGX_LOG_DEBUG_CORE, cycle->log, 0,
        !           604:                                    "pass close channel s:%i pid:%P to:%P",
        !           605:                                    ch.slot, ch.pid, ngx_processes[n].pid);
        !           606: 
        !           607:                     /* TODO: NGX_AGAIN */
        !           608: 
        !           609:                     ngx_write_channel(ngx_processes[n].channel[0],
        !           610:                                       &ch, sizeof(ngx_channel_t), cycle->log);
        !           611:                 }
        !           612:             }
        !           613: 
        !           614:             if (ngx_processes[i].respawn
        !           615:                 && !ngx_processes[i].exiting
        !           616:                 && !ngx_terminate
        !           617:                 && !ngx_quit)
        !           618:             {
        !           619:                 if (ngx_spawn_process(cycle, ngx_processes[i].proc,
        !           620:                                       ngx_processes[i].data,
        !           621:                                       ngx_processes[i].name, i)
        !           622:                     == NGX_INVALID_PID)
        !           623:                 {
        !           624:                     ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
        !           625:                                   "could not respawn %s",
        !           626:                                   ngx_processes[i].name);
        !           627:                     continue;
        !           628:                 }
        !           629: 
        !           630: 
        !           631:                 ch.command = NGX_CMD_OPEN_CHANNEL;
        !           632:                 ch.pid = ngx_processes[ngx_process_slot].pid;
        !           633:                 ch.slot = ngx_process_slot;
        !           634:                 ch.fd = ngx_processes[ngx_process_slot].channel[0];
        !           635: 
        !           636:                 ngx_pass_open_channel(cycle, &ch);
        !           637: 
        !           638:                 live = 1;
        !           639: 
        !           640:                 continue;
        !           641:             }
        !           642: 
        !           643:             if (ngx_processes[i].pid == ngx_new_binary) {
        !           644: 
        !           645:                 ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx,
        !           646:                                                        ngx_core_module);
        !           647: 
        !           648:                 if (ngx_rename_file((char *) ccf->oldpid.data,
        !           649:                                     (char *) ccf->pid.data)
        !           650:                     == NGX_FILE_ERROR)
        !           651:                 {
        !           652:                     ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
        !           653:                                   ngx_rename_file_n " %s back to %s failed "
        !           654:                                   "after the new binary process \"%s\" exited",
        !           655:                                   ccf->oldpid.data, ccf->pid.data, ngx_argv[0]);
        !           656:                 }
        !           657: 
        !           658:                 ngx_new_binary = 0;
        !           659:                 if (ngx_noaccepting) {
        !           660:                     ngx_restart = 1;
        !           661:                     ngx_noaccepting = 0;
        !           662:                 }
        !           663:             }
        !           664: 
        !           665:             if (i == ngx_last_process - 1) {
        !           666:                 ngx_last_process--;
        !           667: 
        !           668:             } else {
        !           669:                 ngx_processes[i].pid = -1;
        !           670:             }
        !           671: 
        !           672:         } else if (ngx_processes[i].exiting || !ngx_processes[i].detached) {
        !           673:             live = 1;
        !           674:         }
        !           675:     }
        !           676: 
        !           677:     return live;
        !           678: }
        !           679: 
        !           680: 
        !           681: static void
        !           682: ngx_master_process_exit(ngx_cycle_t *cycle)
        !           683: {
        !           684:     ngx_uint_t  i;
        !           685: 
        !           686:     ngx_delete_pidfile(cycle);
        !           687: 
        !           688:     ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exit");
        !           689: 
        !           690:     for (i = 0; ngx_modules[i]; i++) {
        !           691:         if (ngx_modules[i]->exit_master) {
        !           692:             ngx_modules[i]->exit_master(cycle);
        !           693:         }
        !           694:     }
        !           695: 
        !           696:     ngx_close_listening_sockets(cycle);
        !           697: 
        !           698:     /*
        !           699:      * Copy ngx_cycle->log related data to the special static exit cycle,
        !           700:      * log, and log file structures enough to allow a signal handler to log.
        !           701:      * The handler may be called when standard ngx_cycle->log allocated from
        !           702:      * ngx_cycle->pool is already destroyed.
        !           703:      */
        !           704: 
        !           705:     ngx_exit_log_file.fd = ngx_cycle->log->file->fd;
        !           706: 
        !           707:     ngx_exit_log = *ngx_cycle->log;
        !           708:     ngx_exit_log.file = &ngx_exit_log_file;
        !           709: 
        !           710:     ngx_exit_cycle.log = &ngx_exit_log;
        !           711:     ngx_exit_cycle.files = ngx_cycle->files;
        !           712:     ngx_exit_cycle.files_n = ngx_cycle->files_n;
        !           713:     ngx_cycle = &ngx_exit_cycle;
        !           714: 
        !           715:     ngx_destroy_pool(cycle->pool);
        !           716: 
        !           717:     exit(0);
        !           718: }
        !           719: 
        !           720: 
        !           721: static void
        !           722: ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data)
        !           723: {
        !           724:     ngx_int_t worker = (intptr_t) data;
        !           725: 
        !           726:     ngx_uint_t         i;
        !           727:     ngx_connection_t  *c;
        !           728: 
        !           729:     ngx_process = NGX_PROCESS_WORKER;
        !           730: 
        !           731:     ngx_worker_process_init(cycle, worker);
        !           732: 
        !           733:     ngx_setproctitle("worker process");
        !           734: 
        !           735: #if (NGX_THREADS)
        !           736:     {
        !           737:     ngx_int_t         n;
        !           738:     ngx_err_t         err;
        !           739:     ngx_core_conf_t  *ccf;
        !           740: 
        !           741:     ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
        !           742: 
        !           743:     if (ngx_threads_n) {
        !           744:         if (ngx_init_threads(ngx_threads_n, ccf->thread_stack_size, cycle)
        !           745:             == NGX_ERROR)
        !           746:         {
        !           747:             /* fatal */
        !           748:             exit(2);
        !           749:         }
        !           750: 
        !           751:         err = ngx_thread_key_create(&ngx_core_tls_key);
        !           752:         if (err != 0) {
        !           753:             ngx_log_error(NGX_LOG_ALERT, cycle->log, err,
        !           754:                           ngx_thread_key_create_n " failed");
        !           755:             /* fatal */
        !           756:             exit(2);
        !           757:         }
        !           758: 
        !           759:         for (n = 0; n < ngx_threads_n; n++) {
        !           760: 
        !           761:             ngx_threads[n].cv = ngx_cond_init(cycle->log);
        !           762: 
        !           763:             if (ngx_threads[n].cv == NULL) {
        !           764:                 /* fatal */
        !           765:                 exit(2);
        !           766:             }
        !           767: 
        !           768:             if (ngx_create_thread((ngx_tid_t *) &ngx_threads[n].tid,
        !           769:                                   ngx_worker_thread_cycle,
        !           770:                                   (void *) &ngx_threads[n], cycle->log)
        !           771:                 != 0)
        !           772:             {
        !           773:                 /* fatal */
        !           774:                 exit(2);
        !           775:             }
        !           776:         }
        !           777:     }
        !           778:     }
        !           779: #endif
        !           780: 
        !           781:     for ( ;; ) {
        !           782: 
        !           783:         if (ngx_exiting) {
        !           784: 
        !           785:             c = cycle->connections;
        !           786: 
        !           787:             for (i = 0; i < cycle->connection_n; i++) {
        !           788: 
        !           789:                 /* THREAD: lock */
        !           790: 
        !           791:                 if (c[i].fd != -1 && c[i].idle) {
        !           792:                     c[i].close = 1;
        !           793:                     c[i].read->handler(c[i].read);
        !           794:                 }
        !           795:             }
        !           796: 
        !           797:             if (ngx_event_timer_rbtree.root == ngx_event_timer_rbtree.sentinel)
        !           798:             {
        !           799:                 ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exiting");
        !           800: 
        !           801:                 ngx_worker_process_exit(cycle);
        !           802:             }
        !           803:         }
        !           804: 
        !           805:         ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "worker cycle");
        !           806: 
        !           807:         ngx_process_events_and_timers(cycle);
        !           808: 
        !           809:         if (ngx_terminate) {
        !           810:             ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exiting");
        !           811: 
        !           812:             ngx_worker_process_exit(cycle);
        !           813:         }
        !           814: 
        !           815:         if (ngx_quit) {
        !           816:             ngx_quit = 0;
        !           817:             ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0,
        !           818:                           "gracefully shutting down");
        !           819:             ngx_setproctitle("worker process is shutting down");
        !           820: 
        !           821:             if (!ngx_exiting) {
        !           822:                 ngx_close_listening_sockets(cycle);
        !           823:                 ngx_exiting = 1;
        !           824:             }
        !           825:         }
        !           826: 
        !           827:         if (ngx_reopen) {
        !           828:             ngx_reopen = 0;
        !           829:             ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reopening logs");
        !           830:             ngx_reopen_files(cycle, -1);
        !           831:         }
        !           832:     }
        !           833: }
        !           834: 
        !           835: 
        !           836: static void
        !           837: ngx_worker_process_init(ngx_cycle_t *cycle, ngx_int_t worker)
        !           838: {
        !           839:     sigset_t          set;
        !           840:     uint64_t          cpu_affinity;
        !           841:     ngx_int_t         n;
        !           842:     ngx_uint_t        i;
        !           843:     struct rlimit     rlmt;
        !           844:     ngx_core_conf_t  *ccf;
        !           845:     ngx_listening_t  *ls;
        !           846: 
        !           847:     if (ngx_set_environment(cycle, NULL) == NULL) {
        !           848:         /* fatal */
        !           849:         exit(2);
        !           850:     }
        !           851: 
        !           852:     ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
        !           853: 
        !           854:     if (worker >= 0 && ccf->priority != 0) {
        !           855:         if (setpriority(PRIO_PROCESS, 0, ccf->priority) == -1) {
        !           856:             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
        !           857:                           "setpriority(%d) failed", ccf->priority);
        !           858:         }
        !           859:     }
        !           860: 
        !           861:     if (ccf->rlimit_nofile != NGX_CONF_UNSET) {
        !           862:         rlmt.rlim_cur = (rlim_t) ccf->rlimit_nofile;
        !           863:         rlmt.rlim_max = (rlim_t) ccf->rlimit_nofile;
        !           864: 
        !           865:         if (setrlimit(RLIMIT_NOFILE, &rlmt) == -1) {
        !           866:             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
        !           867:                           "setrlimit(RLIMIT_NOFILE, %i) failed",
        !           868:                           ccf->rlimit_nofile);
        !           869:         }
        !           870:     }
        !           871: 
        !           872:     if (ccf->rlimit_core != NGX_CONF_UNSET) {
        !           873:         rlmt.rlim_cur = (rlim_t) ccf->rlimit_core;
        !           874:         rlmt.rlim_max = (rlim_t) ccf->rlimit_core;
        !           875: 
        !           876:         if (setrlimit(RLIMIT_CORE, &rlmt) == -1) {
        !           877:             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
        !           878:                           "setrlimit(RLIMIT_CORE, %O) failed",
        !           879:                           ccf->rlimit_core);
        !           880:         }
        !           881:     }
        !           882: 
        !           883: #ifdef RLIMIT_SIGPENDING
        !           884:     if (ccf->rlimit_sigpending != NGX_CONF_UNSET) {
        !           885:         rlmt.rlim_cur = (rlim_t) ccf->rlimit_sigpending;
        !           886:         rlmt.rlim_max = (rlim_t) ccf->rlimit_sigpending;
        !           887: 
        !           888:         if (setrlimit(RLIMIT_SIGPENDING, &rlmt) == -1) {
        !           889:             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
        !           890:                           "setrlimit(RLIMIT_SIGPENDING, %i) failed",
        !           891:                           ccf->rlimit_sigpending);
        !           892:         }
        !           893:     }
        !           894: #endif
        !           895: 
        !           896:     if (geteuid() == 0) {
        !           897:         if (setgid(ccf->group) == -1) {
        !           898:             ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
        !           899:                           "setgid(%d) failed", ccf->group);
        !           900:             /* fatal */
        !           901:             exit(2);
        !           902:         }
        !           903: 
        !           904:         if (initgroups(ccf->username, ccf->group) == -1) {
        !           905:             ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
        !           906:                           "initgroups(%s, %d) failed",
        !           907:                           ccf->username, ccf->group);
        !           908:         }
        !           909: 
        !           910:         if (setuid(ccf->user) == -1) {
        !           911:             ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
        !           912:                           "setuid(%d) failed", ccf->user);
        !           913:             /* fatal */
        !           914:             exit(2);
        !           915:         }
        !           916:     }
        !           917: 
        !           918:     if (worker >= 0) {
        !           919:         cpu_affinity = ngx_get_cpu_affinity(worker);
        !           920: 
        !           921:         if (cpu_affinity) {
        !           922:             ngx_setaffinity(cpu_affinity, cycle->log);
        !           923:         }
        !           924:     }
        !           925: 
        !           926: #if (NGX_HAVE_PR_SET_DUMPABLE)
        !           927: 
        !           928:     /* allow coredump after setuid() in Linux 2.4.x */
        !           929: 
        !           930:     if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) == -1) {
        !           931:         ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
        !           932:                       "prctl(PR_SET_DUMPABLE) failed");
        !           933:     }
        !           934: 
        !           935: #endif
        !           936: 
        !           937:     if (ccf->working_directory.len) {
        !           938:         if (chdir((char *) ccf->working_directory.data) == -1) {
        !           939:             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
        !           940:                           "chdir(\"%s\") failed", ccf->working_directory.data);
        !           941:             /* fatal */
        !           942:             exit(2);
        !           943:         }
        !           944:     }
        !           945: 
        !           946:     sigemptyset(&set);
        !           947: 
        !           948:     if (sigprocmask(SIG_SETMASK, &set, NULL) == -1) {
        !           949:         ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
        !           950:                       "sigprocmask() failed");
        !           951:     }
        !           952: 
        !           953:     /*
        !           954:      * disable deleting previous events for the listening sockets because
        !           955:      * in the worker processes there are no events at all at this point
        !           956:      */
        !           957:     ls = cycle->listening.elts;
        !           958:     for (i = 0; i < cycle->listening.nelts; i++) {
        !           959:         ls[i].previous = NULL;
        !           960:     }
        !           961: 
        !           962:     for (i = 0; ngx_modules[i]; i++) {
        !           963:         if (ngx_modules[i]->init_process) {
        !           964:             if (ngx_modules[i]->init_process(cycle) == NGX_ERROR) {
        !           965:                 /* fatal */
        !           966:                 exit(2);
        !           967:             }
        !           968:         }
        !           969:     }
        !           970: 
        !           971:     for (n = 0; n < ngx_last_process; n++) {
        !           972: 
        !           973:         if (ngx_processes[n].pid == -1) {
        !           974:             continue;
        !           975:         }
        !           976: 
        !           977:         if (n == ngx_process_slot) {
        !           978:             continue;
        !           979:         }
        !           980: 
        !           981:         if (ngx_processes[n].channel[1] == -1) {
        !           982:             continue;
        !           983:         }
        !           984: 
        !           985:         if (close(ngx_processes[n].channel[1]) == -1) {
        !           986:             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
        !           987:                           "close() channel failed");
        !           988:         }
        !           989:     }
        !           990: 
        !           991:     if (close(ngx_processes[ngx_process_slot].channel[0]) == -1) {
        !           992:         ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
        !           993:                       "close() channel failed");
        !           994:     }
        !           995: 
        !           996: #if 0
        !           997:     ngx_last_process = 0;
        !           998: #endif
        !           999: 
        !          1000:     if (ngx_add_channel_event(cycle, ngx_channel, NGX_READ_EVENT,
        !          1001:                               ngx_channel_handler)
        !          1002:         == NGX_ERROR)
        !          1003:     {
        !          1004:         /* fatal */
        !          1005:         exit(2);
        !          1006:     }
        !          1007: }
        !          1008: 
        !          1009: 
        !          1010: static void
        !          1011: ngx_worker_process_exit(ngx_cycle_t *cycle)
        !          1012: {
        !          1013:     ngx_uint_t         i;
        !          1014:     ngx_connection_t  *c;
        !          1015: 
        !          1016: #if (NGX_THREADS)
        !          1017:     ngx_terminate = 1;
        !          1018: 
        !          1019:     ngx_wakeup_worker_threads(cycle);
        !          1020: #endif
        !          1021: 
        !          1022:     for (i = 0; ngx_modules[i]; i++) {
        !          1023:         if (ngx_modules[i]->exit_process) {
        !          1024:             ngx_modules[i]->exit_process(cycle);
        !          1025:         }
        !          1026:     }
        !          1027: 
        !          1028:     if (ngx_exiting) {
        !          1029:         c = cycle->connections;
        !          1030:         for (i = 0; i < cycle->connection_n; i++) {
        !          1031:             if (c[i].fd != -1
        !          1032:                 && c[i].read
        !          1033:                 && !c[i].read->accept
        !          1034:                 && !c[i].read->channel
        !          1035:                 && !c[i].read->resolver)
        !          1036:             {
        !          1037:                 ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
        !          1038:                               "open socket #%d left in connection %ui",
        !          1039:                               c[i].fd, i);
        !          1040:                 ngx_debug_quit = 1;
        !          1041:             }
        !          1042:         }
        !          1043: 
        !          1044:         if (ngx_debug_quit) {
        !          1045:             ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "aborting");
        !          1046:             ngx_debug_point();
        !          1047:         }
        !          1048:     }
        !          1049: 
        !          1050:     /*
        !          1051:      * Copy ngx_cycle->log related data to the special static exit cycle,
        !          1052:      * log, and log file structures enough to allow a signal handler to log.
        !          1053:      * The handler may be called when standard ngx_cycle->log allocated from
        !          1054:      * ngx_cycle->pool is already destroyed.
        !          1055:      */
        !          1056: 
        !          1057:     ngx_exit_log_file.fd = ngx_cycle->log->file->fd;
        !          1058: 
        !          1059:     ngx_exit_log = *ngx_cycle->log;
        !          1060:     ngx_exit_log.file = &ngx_exit_log_file;
        !          1061: 
        !          1062:     ngx_exit_cycle.log = &ngx_exit_log;
        !          1063:     ngx_exit_cycle.files = ngx_cycle->files;
        !          1064:     ngx_exit_cycle.files_n = ngx_cycle->files_n;
        !          1065:     ngx_cycle = &ngx_exit_cycle;
        !          1066: 
        !          1067:     ngx_destroy_pool(cycle->pool);
        !          1068: 
        !          1069:     ngx_log_error(NGX_LOG_NOTICE, ngx_cycle->log, 0, "exit");
        !          1070: 
        !          1071:     exit(0);
        !          1072: }
        !          1073: 
        !          1074: 
        !          1075: static void
        !          1076: ngx_channel_handler(ngx_event_t *ev)
        !          1077: {
        !          1078:     ngx_int_t          n;
        !          1079:     ngx_channel_t      ch;
        !          1080:     ngx_connection_t  *c;
        !          1081: 
        !          1082:     if (ev->timedout) {
        !          1083:         ev->timedout = 0;
        !          1084:         return;
        !          1085:     }
        !          1086: 
        !          1087:     c = ev->data;
        !          1088: 
        !          1089:     ngx_log_debug0(NGX_LOG_DEBUG_CORE, ev->log, 0, "channel handler");
        !          1090: 
        !          1091:     for ( ;; ) {
        !          1092: 
        !          1093:         n = ngx_read_channel(c->fd, &ch, sizeof(ngx_channel_t), ev->log);
        !          1094: 
        !          1095:         ngx_log_debug1(NGX_LOG_DEBUG_CORE, ev->log, 0, "channel: %i", n);
        !          1096: 
        !          1097:         if (n == NGX_ERROR) {
        !          1098: 
        !          1099:             if (ngx_event_flags & NGX_USE_EPOLL_EVENT) {
        !          1100:                 ngx_del_conn(c, 0);
        !          1101:             }
        !          1102: 
        !          1103:             ngx_close_connection(c);
        !          1104:             return;
        !          1105:         }
        !          1106: 
        !          1107:         if (ngx_event_flags & NGX_USE_EVENTPORT_EVENT) {
        !          1108:             if (ngx_add_event(ev, NGX_READ_EVENT, 0) == NGX_ERROR) {
        !          1109:                 return;
        !          1110:             }
        !          1111:         }
        !          1112: 
        !          1113:         if (n == NGX_AGAIN) {
        !          1114:             return;
        !          1115:         }
        !          1116: 
        !          1117:         ngx_log_debug1(NGX_LOG_DEBUG_CORE, ev->log, 0,
        !          1118:                        "channel command: %d", ch.command);
        !          1119: 
        !          1120:         switch (ch.command) {
        !          1121: 
        !          1122:         case NGX_CMD_QUIT:
        !          1123:             ngx_quit = 1;
        !          1124:             break;
        !          1125: 
        !          1126:         case NGX_CMD_TERMINATE:
        !          1127:             ngx_terminate = 1;
        !          1128:             break;
        !          1129: 
        !          1130:         case NGX_CMD_REOPEN:
        !          1131:             ngx_reopen = 1;
        !          1132:             break;
        !          1133: 
        !          1134:         case NGX_CMD_OPEN_CHANNEL:
        !          1135: 
        !          1136:             ngx_log_debug3(NGX_LOG_DEBUG_CORE, ev->log, 0,
        !          1137:                            "get channel s:%i pid:%P fd:%d",
        !          1138:                            ch.slot, ch.pid, ch.fd);
        !          1139: 
        !          1140:             ngx_processes[ch.slot].pid = ch.pid;
        !          1141:             ngx_processes[ch.slot].channel[0] = ch.fd;
        !          1142:             break;
        !          1143: 
        !          1144:         case NGX_CMD_CLOSE_CHANNEL:
        !          1145: 
        !          1146:             ngx_log_debug4(NGX_LOG_DEBUG_CORE, ev->log, 0,
        !          1147:                            "close channel s:%i pid:%P our:%P fd:%d",
        !          1148:                            ch.slot, ch.pid, ngx_processes[ch.slot].pid,
        !          1149:                            ngx_processes[ch.slot].channel[0]);
        !          1150: 
        !          1151:             if (close(ngx_processes[ch.slot].channel[0]) == -1) {
        !          1152:                 ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno,
        !          1153:                               "close() channel failed");
        !          1154:             }
        !          1155: 
        !          1156:             ngx_processes[ch.slot].channel[0] = -1;
        !          1157:             break;
        !          1158:         }
        !          1159:     }
        !          1160: }
        !          1161: 
        !          1162: 
        !          1163: #if (NGX_THREADS)
        !          1164: 
        !          1165: static void
        !          1166: ngx_wakeup_worker_threads(ngx_cycle_t *cycle)
        !          1167: {
        !          1168:     ngx_int_t   i;
        !          1169:     ngx_uint_t  live;
        !          1170: 
        !          1171:     for ( ;; ) {
        !          1172: 
        !          1173:         live = 0;
        !          1174: 
        !          1175:         for (i = 0; i < ngx_threads_n; i++) {
        !          1176:             if (ngx_threads[i].state < NGX_THREAD_EXIT) {
        !          1177:                 if (ngx_cond_signal(ngx_threads[i].cv) == NGX_ERROR) {
        !          1178:                     ngx_threads[i].state = NGX_THREAD_DONE;
        !          1179: 
        !          1180:                 } else {
        !          1181:                     live = 1;
        !          1182:                 }
        !          1183:             }
        !          1184: 
        !          1185:             if (ngx_threads[i].state == NGX_THREAD_EXIT) {
        !          1186:                 ngx_thread_join(ngx_threads[i].tid, NULL);
        !          1187:                 ngx_threads[i].state = NGX_THREAD_DONE;
        !          1188:             }
        !          1189:         }
        !          1190: 
        !          1191:         if (live == 0) {
        !          1192:             ngx_log_debug0(NGX_LOG_DEBUG_CORE, cycle->log, 0,
        !          1193:                            "all worker threads are joined");
        !          1194: 
        !          1195:             /* STUB */
        !          1196:             ngx_done_events(cycle);
        !          1197:             ngx_mutex_destroy(ngx_event_timer_mutex);
        !          1198:             ngx_mutex_destroy(ngx_posted_events_mutex);
        !          1199: 
        !          1200:             return;
        !          1201:         }
        !          1202: 
        !          1203:         ngx_sched_yield();
        !          1204:     }
        !          1205: }
        !          1206: 
        !          1207: 
        !          1208: static ngx_thread_value_t
        !          1209: ngx_worker_thread_cycle(void *data)
        !          1210: {
        !          1211:     ngx_thread_t  *thr = data;
        !          1212: 
        !          1213:     sigset_t          set;
        !          1214:     ngx_err_t         err;
        !          1215:     ngx_core_tls_t   *tls;
        !          1216:     ngx_cycle_t      *cycle;
        !          1217: 
        !          1218:     cycle = (ngx_cycle_t *) ngx_cycle;
        !          1219: 
        !          1220:     sigemptyset(&set);
        !          1221:     sigaddset(&set, ngx_signal_value(NGX_RECONFIGURE_SIGNAL));
        !          1222:     sigaddset(&set, ngx_signal_value(NGX_REOPEN_SIGNAL));
        !          1223:     sigaddset(&set, ngx_signal_value(NGX_CHANGEBIN_SIGNAL));
        !          1224: 
        !          1225:     err = ngx_thread_sigmask(SIG_BLOCK, &set, NULL);
        !          1226:     if (err) {
        !          1227:         ngx_log_error(NGX_LOG_ALERT, cycle->log, err,
        !          1228:                       ngx_thread_sigmask_n " failed");
        !          1229:         return (ngx_thread_value_t) 1;
        !          1230:     }
        !          1231: 
        !          1232:     ngx_log_debug1(NGX_LOG_DEBUG_CORE, cycle->log, 0,
        !          1233:                    "thread " NGX_TID_T_FMT " started", ngx_thread_self());
        !          1234: 
        !          1235:     ngx_setthrtitle("worker thread");
        !          1236: 
        !          1237:     tls = ngx_calloc(sizeof(ngx_core_tls_t), cycle->log);
        !          1238:     if (tls == NULL) {
        !          1239:         return (ngx_thread_value_t) 1;
        !          1240:     }
        !          1241: 
        !          1242:     err = ngx_thread_set_tls(ngx_core_tls_key, tls);
        !          1243:     if (err != 0) {
        !          1244:         ngx_log_error(NGX_LOG_ALERT, cycle->log, err,
        !          1245:                       ngx_thread_set_tls_n " failed");
        !          1246:         return (ngx_thread_value_t) 1;
        !          1247:     }
        !          1248: 
        !          1249:     ngx_mutex_lock(ngx_posted_events_mutex);
        !          1250: 
        !          1251:     for ( ;; ) {
        !          1252:         thr->state = NGX_THREAD_FREE;
        !          1253: 
        !          1254:         if (ngx_cond_wait(thr->cv, ngx_posted_events_mutex) == NGX_ERROR) {
        !          1255:             return (ngx_thread_value_t) 1;
        !          1256:         }
        !          1257: 
        !          1258:         if (ngx_terminate) {
        !          1259:             thr->state = NGX_THREAD_EXIT;
        !          1260: 
        !          1261:             ngx_mutex_unlock(ngx_posted_events_mutex);
        !          1262: 
        !          1263:             ngx_log_debug1(NGX_LOG_DEBUG_CORE, cycle->log, 0,
        !          1264:                            "thread " NGX_TID_T_FMT " is done",
        !          1265:                            ngx_thread_self());
        !          1266: 
        !          1267:             return (ngx_thread_value_t) 0;
        !          1268:         }
        !          1269: 
        !          1270:         thr->state = NGX_THREAD_BUSY;
        !          1271: 
        !          1272:         if (ngx_event_thread_process_posted(cycle) == NGX_ERROR) {
        !          1273:             return (ngx_thread_value_t) 1;
        !          1274:         }
        !          1275: 
        !          1276:         if (ngx_event_thread_process_posted(cycle) == NGX_ERROR) {
        !          1277:             return (ngx_thread_value_t) 1;
        !          1278:         }
        !          1279: 
        !          1280:         if (ngx_process_changes) {
        !          1281:             if (ngx_process_changes(cycle, 1) == NGX_ERROR) {
        !          1282:                 return (ngx_thread_value_t) 1;
        !          1283:             }
        !          1284:         }
        !          1285:     }
        !          1286: }
        !          1287: 
        !          1288: #endif
        !          1289: 
        !          1290: 
        !          1291: static void
        !          1292: ngx_cache_manager_process_cycle(ngx_cycle_t *cycle, void *data)
        !          1293: {
        !          1294:     ngx_cache_manager_ctx_t *ctx = data;
        !          1295: 
        !          1296:     void         *ident[4];
        !          1297:     ngx_event_t   ev;
        !          1298: 
        !          1299:     /*
        !          1300:      * Set correct process type since closing listening Unix domain socket
        !          1301:      * in a master process also removes the Unix domain socket file.
        !          1302:      */
        !          1303:     ngx_process = NGX_PROCESS_HELPER;
        !          1304: 
        !          1305:     ngx_close_listening_sockets(cycle);
        !          1306: 
        !          1307:     /* Set a moderate number of connections for a helper process. */
        !          1308:     cycle->connection_n = 512;
        !          1309: 
        !          1310:     ngx_worker_process_init(cycle, -1);
        !          1311: 
        !          1312:     ngx_memzero(&ev, sizeof(ngx_event_t));
        !          1313:     ev.handler = ctx->handler;
        !          1314:     ev.data = ident;
        !          1315:     ev.log = cycle->log;
        !          1316:     ident[3] = (void *) -1;
        !          1317: 
        !          1318:     ngx_use_accept_mutex = 0;
        !          1319: 
        !          1320:     ngx_setproctitle(ctx->name);
        !          1321: 
        !          1322:     ngx_add_timer(&ev, ctx->delay);
        !          1323: 
        !          1324:     for ( ;; ) {
        !          1325: 
        !          1326:         if (ngx_terminate || ngx_quit) {
        !          1327:             ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exiting");
        !          1328:             exit(0);
        !          1329:         }
        !          1330: 
        !          1331:         if (ngx_reopen) {
        !          1332:             ngx_reopen = 0;
        !          1333:             ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reopening logs");
        !          1334:             ngx_reopen_files(cycle, -1);
        !          1335:         }
        !          1336: 
        !          1337:         ngx_process_events_and_timers(cycle);
        !          1338:     }
        !          1339: }
        !          1340: 
        !          1341: 
        !          1342: static void
        !          1343: ngx_cache_manager_process_handler(ngx_event_t *ev)
        !          1344: {
        !          1345:     time_t        next, n;
        !          1346:     ngx_uint_t    i;
        !          1347:     ngx_path_t  **path;
        !          1348: 
        !          1349:     next = 60 * 60;
        !          1350: 
        !          1351:     path = ngx_cycle->paths.elts;
        !          1352:     for (i = 0; i < ngx_cycle->paths.nelts; i++) {
        !          1353: 
        !          1354:         if (path[i]->manager) {
        !          1355:             n = path[i]->manager(path[i]->data);
        !          1356: 
        !          1357:             next = (n <= next) ? n : next;
        !          1358: 
        !          1359:             ngx_time_update();
        !          1360:         }
        !          1361:     }
        !          1362: 
        !          1363:     if (next == 0) {
        !          1364:         next = 1;
        !          1365:     }
        !          1366: 
        !          1367:     ngx_add_timer(ev, next * 1000);
        !          1368: }
        !          1369: 
        !          1370: 
        !          1371: static void
        !          1372: ngx_cache_loader_process_handler(ngx_event_t *ev)
        !          1373: {
        !          1374:     ngx_uint_t     i;
        !          1375:     ngx_path_t   **path;
        !          1376:     ngx_cycle_t   *cycle;
        !          1377: 
        !          1378:     cycle = (ngx_cycle_t *) ngx_cycle;
        !          1379: 
        !          1380:     path = cycle->paths.elts;
        !          1381:     for (i = 0; i < cycle->paths.nelts; i++) {
        !          1382: 
        !          1383:         if (ngx_terminate || ngx_quit) {
        !          1384:             break;
        !          1385:         }
        !          1386: 
        !          1387:         if (path[i]->loader) {
        !          1388:             path[i]->loader(path[i]->data);
        !          1389:             ngx_time_update();
        !          1390:         }
        !          1391:     }
        !          1392: 
        !          1393:     exit(0);
        !          1394: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>