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>