/* 启动缓存管理进程 */ static void ngx_start_cache_manager_processes(ngx_cycle_t *cycle, ngx_uint_t respawn) { ngx_uint_t i, manager, loader; ngx_path_t **path; ngx_channel_t ch; manager = 0; loader = 0; path = ngx_cycle->paths.elts; for (i = 0; i < ngx_cycle->paths.nelts; i++) { /* 判断管理句柄 */ if (path[i]->manager) { manager = 1; } /* 判断加载句柄 */ if (path[i]->loader) { loader = 1; } } if (manager == 0) { return; } /* 启动缓存管理进程 */ ngx_spawn_process(cycle, ngx_cache_manager_process_cycle, &ngx_cache_manager_ctx, "cache manager process", respawn ? NGX_PROCESS_JUST_RESPAWN : NGX_PROCESS_RESPAWN); ngx_memzero(&ch, sizeof(ngx_channel_t)); ch.command = NGX_CMD_OPEN_CHANNEL; ch.pid = ngx_processes[ngx_process_slot].pid; ch.slot = ngx_process_slot; ch.fd = ngx_processes[ngx_process_slot].channel[0]; /* 通知其他worker进程和缓存管理进程的通信fd */ ngx_pass_open_channel(cycle, &ch); if (loader == 0) { return; } /* 启动缓存加载进程 */ ngx_spawn_process(cycle, ngx_cache_manager_process_cycle, &ngx_cache_loader_ctx, "cache loader process", respawn ? NGX_PROCESS_JUST_SPAWN : NGX_PROCESS_NORESPAWN); ch.command = NGX_CMD_OPEN_CHANNEL; ch.pid = ngx_processes[ngx_process_slot].pid; ch.slot = ngx_process_slot; ch.fd = ngx_processes[ngx_process_slot].channel[0]; ngx_pass_open_channel(cycle, &ch); }
/*启动缓存索引重建进程,该进程在整个Nginx服务器运行过程中只存在很短的时间,主要用来遍历磁盘上的缓存数据,在内存中建立数据索引,提高Nginx服务器检索缓存的效率*/ static void ngx_start_cache_manager_processes(ngx_cycle_t *cycle, ngx_uint_t respawn) { ngx_uint_t i, manager, loader; ngx_path_t **path; ngx_channel_t ch; manager = 0; loader = 0; path = ngx_cycle->paths.elts; for (i = 0; i < ngx_cycle->paths.nelts; i++) { if (path[i]->manager) { manager = 1; } if (path[i]->loader) { loader = 1; } } if (manager == 0) { return; } /*创建缓存索引管理进程Cache Manager Process,此时respawn=0,所以传入的参数是NGX_PROCESS_JUST_RESPAWN*/ ngx_spawn_process(cycle, ngx_cache_manager_process_cycle, &ngx_cache_manager_ctx, "cache manager process", respawn ? NGX_PROCESS_JUST_RESPAWN : NGX_PROCESS_RESPAWN); ngx_memzero(&ch, sizeof(ngx_channel_t)); ch.command = NGX_CMD_OPEN_CHANNEL; ch.pid = ngx_processes[ngx_process_slot].pid; ch.slot = ngx_process_slot; ch.fd = ngx_processes[ngx_process_slot].channel[0]; /*创建进程间通信管道*/ ngx_pass_open_channel(cycle, &ch); if (loader == 0) { return; } /*创建缓存索引管理进程Cache Loader Process,此时respawn=0,所以传入的参数是NGX_PROCESS_JUST_SPAWN*/ ngx_spawn_process(cycle, ngx_cache_manager_process_cycle, &ngx_cache_loader_ctx, "cache loader process", respawn ? NGX_PROCESS_JUST_SPAWN : NGX_PROCESS_NORESPAWN); ch.command = NGX_CMD_OPEN_CHANNEL; ch.pid = ngx_processes[ngx_process_slot].pid; ch.slot = ngx_process_slot; ch.fd = ngx_processes[ngx_process_slot].channel[0]; /*创建进程间通信管道*/ ngx_pass_open_channel(cycle, &ch); }
static void ngx_start_cache_manager_processes(ngx_cycle_t *cycle, ngx_uint_t respawn) { ngx_uint_t i, manager, loader; ngx_path_t **path; ngx_channel_t ch; manager = 0; loader = 0; path = ngx_cycle->pathes.elts; for (i = 0; i < ngx_cycle->pathes.nelts; i++) { if (path[i]->manager) { manager = 1; } if (path[i]->loader) { loader = 1; } } if (manager == 0) { return; } ngx_spawn_process(cycle, ngx_cache_manager_process_cycle, &ngx_cache_manager_ctx, "cache manager process", respawn ? NGX_PROCESS_JUST_RESPAWN : NGX_PROCESS_RESPAWN); ch.command = NGX_CMD_OPEN_CHANNEL; ch.pid = ngx_processes[ngx_process_slot].pid; ch.slot = ngx_process_slot; ch.fd = ngx_processes[ngx_process_slot].channel[0]; ngx_pass_open_channel(cycle, &ch); if (loader == 0) { return; } ngx_spawn_process(cycle, ngx_cache_manager_process_cycle, &ngx_cache_loader_ctx, "cache loader process", respawn ? NGX_PROCESS_JUST_SPAWN : NGX_PROCESS_NORESPAWN); ch.command = NGX_CMD_OPEN_CHANNEL; ch.pid = ngx_processes[ngx_process_slot].pid; ch.slot = ngx_process_slot; ch.fd = ngx_processes[ngx_process_slot].channel[0]; ngx_pass_open_channel(cycle, &ch); }
static void ngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t n, ngx_int_t type) { ngx_int_t i; ngx_channel_t ch; ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "start worker processes"); ngx_memzero(&ch, sizeof(ngx_channel_t)); ch.command = NGX_CMD_OPEN_CHANNEL; for (i = 0; i < n; i++) { /*打开主进程和工作进程通信的管道,并fork出子进程,在子进程中运行ngx_worker_process_cycle函数*/ ngx_spawn_process(cycle, ngx_worker_process_cycle, (void *) (intptr_t) i, "worker process", type); ch.pid = ngx_processes[ngx_process_slot].pid; ch.slot = ngx_process_slot; ch.fd = ngx_processes[ngx_process_slot].channel[0]; /*循环遍历所有的工作进程信息,将新打开的进程的PID、slot(也就是下标)、channel[0]发送给其他的进程*/ ngx_pass_open_channel(cycle, &ch); } }
static void ngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t n, ngx_int_t type) { ngx_int_t i; ngx_channel_t ch; ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "start worker processes"); ngx_memzero(&ch, sizeof(ngx_channel_t)); ch.command = NGX_CMD_OPEN_CHANNEL; for (i = 0; i < n; i++) { ngx_spawn_process(cycle, ngx_worker_process_cycle, (void *) (intptr_t) i, "worker process", type); ch.pid = ngx_processes[ngx_process_slot].pid; ch.slot = ngx_process_slot; ch.fd = ngx_processes[ngx_process_slot].channel[0]; //父进程将ngx_spawn_process新创建的进程的channel[0] 传递给进程表中的其他进程 ngx_pass_open_channel(cycle, &ch); } }
/* master进程启动n个子进程 */ static void ngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t n, ngx_int_t type) { ngx_int_t i; ngx_channel_t ch; ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "start worker processes"); ngx_memzero(&ch, sizeof(ngx_channel_t)); ch.command = NGX_CMD_OPEN_CHANNEL; /* 创建n个worker进程 */ for (i = 0; i < n; i++) { /* ngx_worker_process_cycle用来初始化worker进程的主循环 */ ngx_spawn_process(cycle, ngx_worker_process_cycle, (void *) (intptr_t) i, "worker process", type); ch.pid = ngx_processes[ngx_process_slot].pid; ch.slot = ngx_process_slot; /* 将子进程的0通道通知其他在前创建的进程,1通道是接收信息的 */ ch.fd = ngx_processes[ngx_process_slot].channel[0]; /* 把创建的子进程的相关信息通知前面已经生成的子进程, * 注意这里是父进程把刚创建的子进程的相关信息发送给其他子进程, * 而不是子进程自己发送的 */ ngx_pass_open_channel(cycle, &ch); } }
ngx_pid_t ngx_execute(ngx_cycle_t *cycle, ngx_exec_ctx_t *ctx) { //执行的函数是ngx_execute_proc return ngx_spawn_process(cycle, ngx_execute_proc, ctx, ctx->name, NGX_PROCESS_DETACHED); }
// 被ngx_master_process_cycle()调用 // 启动worker进程,数量由配置决定,即worker_processes指令 // 调用时传递的是#define NGX_PROCESS_RESPAWN -3 static void ngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t n, ngx_int_t type) { ngx_int_t i; ngx_channel_t ch; ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "start worker processes"); ngx_memzero(&ch, sizeof(ngx_channel_t)); // unix channel ch.command = NGX_CMD_OPEN_CHANNEL; for (i = 0; i < n; i++) { // os/unix/ngx_process.c产生进程,执行ngx_worker_process_cycle // 创建的进程都在ngx_processes数组里 // 定义在os/unix/ngx_process.c // ngx_process_t ngx_processes[NGX_MAX_PROCESSES]; ngx_spawn_process(cycle, ngx_worker_process_cycle, (void *) (intptr_t) i, "worker process", type); // 设置channel信息 ch.pid = ngx_processes[ngx_process_slot].pid; ch.slot = ngx_process_slot; ch.fd = ngx_processes[ngx_process_slot].channel[0]; // 建立channel,用于进程间通信 ngx_pass_open_channel(cycle, &ch); } }
/*启动工作进程:两个任务,1是设置父子进程通信,2是根据配置循环创建所有的工作进程*/ static void ngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t n, ngx_int_t type) { ngx_int_t i; ngx_channel_t ch; ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "start worker processes"); //传递给其他子进程的命令,打开channel ch.command = NGX_CMD_OPEN_CHANNEL; //创建n个worker进程 for (i = 0; i < n; i++) { cpu_affinity = ngx_get_cpu_affinity(i); //[p]fork新进程的具体工作,ngx_worker_process_cycle函数是工作进程要执行的具体工作 ngx_spawn_process(cycle, ngx_worker_process_cycle, NULL, "worker process", type); //全局数组,定义在src/os/unix/ngx_process.c文件中,存储元素类型是ngx_process_t。 //注意,ngx_process_slot在spawn函数中已经赋值完毕,就是当前子进程的位置 ch.pid = ngx_processes[ngx_process_slot].pid; ch.slot = ngx_process_slot; ch.fd = ngx_processes[ngx_process_slot].channel[0]; //建立通道,用于进程通信 ngx_pass_open_channel(cycle, &ch); } }
static void ngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t n, ngx_int_t type) { ngx_int_t i; ngx_channel_t ch; struct itimerval itv; ngx_log_error(NGX_LOG_INFO, cycle->log, 0, "start worker processes"); ch.command = NGX_CMD_OPEN_CHANNEL; while (n--) { ngx_spawn_process(cycle, ngx_worker_process_cycle, NULL, "worker process", type); ch.pid = ngx_processes[ngx_process_slot].pid; ch.slot = ngx_process_slot; ch.fd = ngx_processes[ngx_process_slot].channel[0]; for (i = 0; i < ngx_last_process; i++) { if (i == ngx_process_slot || ngx_processes[i].pid == -1 || ngx_processes[i].channel[0] == -1) { continue; } ngx_log_debug6(NGX_LOG_DEBUG_CORE, cycle->log, 0, "pass channel s:%d pid:" PID_T_FMT " fd:%d to s:%d pid:" PID_T_FMT " fd:%d", ch.slot, ch.pid, ch.fd, i, ngx_processes[i].pid, ngx_processes[i].channel[0]); /* TODO: NGX_AGAIN */ ngx_write_channel(ngx_processes[i].channel[0], &ch, sizeof(ngx_channel_t), cycle->log); } } /* * we have to limit the maximum life time of the worker processes * by 10 days because our millisecond event timer is limited * by 24 days on 32-bit platforms */ itv.it_interval.tv_sec = 0; itv.it_interval.tv_usec = 0; itv.it_value.tv_sec = 10 * 24 * 60 * 60; itv.it_value.tv_usec = 0; if (setitimer(ITIMER_REAL, &itv, NULL) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "setitimer() failed"); } }
static ngx_int_t ngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t type) { ngx_int_t n; ngx_core_conf_t *ccf; ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "start worker processes"); ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); for (n = 0; n < ccf->worker_processes; n++) { if (ngx_spawn_process(cycle, "worker", type) == NGX_INVALID_PID) { break; } } return n; }
static void ngx_start_session_manager_processes(ngx_cycle_t *cycle, ngx_uint_t respawn) { ngx_channel_t ch; if (!cycle->session_enabled) { return; } ngx_spawn_process(cycle, ngx_session_manager_process_cycle, &ngx_session_manager_ctx, "session manager process", respawn ? NGX_PROCESS_JUST_RESPAWN : NGX_PROCESS_RESPAWN); ch.command = NGX_CMD_OPEN_CHANNEL; ch.pid = ngx_processes[ngx_process_slot].pid; ch.slot = ngx_process_slot; ch.fd = ngx_processes[ngx_process_slot].channel[0]; ngx_pass_open_channel(cycle, &ch); }
static void ngx_start_ip_blacklist_manager_processes(ngx_cycle_t *cycle, ngx_uint_t respawn) { ngx_channel_t ch; if (!cycle->ip_blacklist_enabled) { /* ip blacklist not enabled, don't start the helper */ return; } ngx_spawn_process(cycle, ngx_ip_blacklist_manager_process_cycle, &ngx_ip_blacklist_manager_ctx, "IP blacklist manager process", respawn ? NGX_PROCESS_JUST_RESPAWN : NGX_PROCESS_RESPAWN); ch.command = NGX_CMD_OPEN_CHANNEL; ch.pid = ngx_processes[ngx_process_slot].pid; ch.slot = ngx_process_slot; ch.fd = ngx_processes[ngx_process_slot].channel[0]; ngx_pass_open_channel(cycle, &ch); }
static void ngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t n, ngx_int_t type) { ngx_int_t i; ngx_channel_t ch; ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "start worker processes"); // 传递给子进程的命令 ch.command = NGX_CMD_OPEN_CHANNEL; for (i = 0; i < n; i++) { // fork子进程 ngx_spawn_process(cycle, ngx_worker_process_cycle, (void *) (intptr_t) i, "worker process", type); // 初始化channel,ngx_process_slot在ngx_spawn_process中已经赋值 ch.pid = ngx_processes[ngx_process_slot].pid; ch.slot = ngx_process_slot; ch.fd = ngx_processes[ngx_process_slot].channel[0]; ngx_pass_open_channel(cycle, &ch); } }
static void ngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t n, ngx_int_t type) { ngx_int_t i; ngx_channel_t ch; ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "start worker processes"); ch.command = NGX_CMD_OPEN_CHANNEL; for (i = 0; i < n; i++) { cpu_affinity = ngx_get_cpu_affinity(i); ngx_spawn_process(cycle, ngx_worker_process_cycle, NULL, "worker process", type); ch.pid = ngx_processes[ngx_process_slot].pid; ch.slot = ngx_process_slot; ch.fd = ngx_processes[ngx_process_slot].channel[0]; ngx_pass_open_channel(cycle, &ch); } }
static ngx_uint_t ngx_reap_children(ngx_cycle_t *cycle) { ngx_int_t i, n; ngx_uint_t live; ngx_channel_t ch; ngx_core_conf_t *ccf; ngx_memzero(&ch, sizeof(ngx_channel_t)); ch.command = NGX_CMD_CLOSE_CHANNEL; ch.fd = -1; live = 0; for (i = 0; i < ngx_last_process; i++) { ngx_log_debug7(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "child: %d %P e:%d t:%d d:%d r:%d j:%d", i, ngx_processes[i].pid, ngx_processes[i].exiting, ngx_processes[i].exited, ngx_processes[i].detached, ngx_processes[i].respawn, ngx_processes[i].just_spawn); if (ngx_processes[i].pid == -1) { continue; } if (ngx_processes[i].exited) { if (!ngx_processes[i].detached) { ngx_close_channel(ngx_processes[i].channel, cycle->log); ngx_processes[i].channel[0] = -1; ngx_processes[i].channel[1] = -1; ch.pid = ngx_processes[i].pid; ch.slot = i; for (n = 0; n < ngx_last_process; n++) { if (ngx_processes[n].exited || ngx_processes[n].pid == -1 || ngx_processes[n].channel[0] == -1) { continue; } ngx_log_debug3(NGX_LOG_DEBUG_CORE, cycle->log, 0, "pass close channel s:%i pid:%P to:%P", ch.slot, ch.pid, ngx_processes[n].pid); /* TODO: NGX_AGAIN */ ngx_write_channel(ngx_processes[n].channel[0], &ch, sizeof(ngx_channel_t), cycle->log); } } if (ngx_processes[i].respawn && !ngx_processes[i].exiting && !ngx_terminate && !ngx_quit) { if (ngx_spawn_process(cycle, ngx_processes[i].proc, ngx_processes[i].data, ngx_processes[i].name, i) == NGX_INVALID_PID) { ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "could not respawn %s", ngx_processes[i].name); continue; } ch.command = NGX_CMD_OPEN_CHANNEL; ch.pid = ngx_processes[ngx_process_slot].pid; ch.slot = ngx_process_slot; ch.fd = ngx_processes[ngx_process_slot].channel[0]; ngx_pass_open_channel(cycle, &ch); live = 1; continue; } if (ngx_processes[i].pid == ngx_new_binary) { ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); if (ngx_rename_file((char *) ccf->oldpid.data, (char *) ccf->pid.data) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, ngx_rename_file_n " %s back to %s failed " "after the new binary process \"%s\" exited", ccf->oldpid.data, ccf->pid.data, ngx_argv[0]); } ngx_new_binary = 0; if (ngx_noaccepting) { ngx_restart = 1; ngx_noaccepting = 0; } } if (i == ngx_last_process - 1) { ngx_last_process--; } else { ngx_processes[i].pid = -1; } } else if (ngx_processes[i].exiting || !ngx_processes[i].detached) { live = 1; } } return live; }
static ngx_uint_t ngx_reap_childs(ngx_cycle_t *cycle) { ngx_int_t i, n; ngx_uint_t live; ngx_channel_t ch; ch.command = NGX_CMD_CLOSE_CHANNEL; ch.fd = -1; live = 0; for (i = 0; i < ngx_last_process; i++) { ngx_log_debug7(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "child: %d " PID_T_FMT " e:%d t:%d d:%d r:%d j:%d", i, ngx_processes[i].pid, ngx_processes[i].exiting, ngx_processes[i].exited, ngx_processes[i].detached, ngx_processes[i].respawn, ngx_processes[i].just_respawn); if (ngx_processes[i].pid == -1) { continue; } if (ngx_processes[i].exited) { if (!ngx_processes[i].detached) { ngx_close_channel(ngx_processes[i].channel, cycle->log); ngx_processes[i].channel[0] = -1; ngx_processes[i].channel[1] = -1; ch.pid = ngx_processes[i].pid; ch.slot = i; for (n = 0; n < ngx_last_process; n++) { if (ngx_processes[n].exited || ngx_processes[n].pid == -1 || ngx_processes[n].channel[0] == -1) { continue; } ngx_log_debug3(NGX_LOG_DEBUG_CORE, cycle->log, 0, "pass close channel s:%d pid:" PID_T_FMT " to:" PID_T_FMT, ch.slot, ch.pid, ngx_processes[n].pid); /* TODO: NGX_AGAIN */ ngx_write_channel(ngx_processes[n].channel[0], &ch, sizeof(ngx_channel_t), cycle->log); } } if (ngx_processes[i].respawn && !ngx_processes[i].exiting && !ngx_terminate && !ngx_quit) { if (ngx_spawn_process(cycle, ngx_processes[i].proc, ngx_processes[i].data, ngx_processes[i].name, i) == NGX_ERROR) { ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "can not respawn %s", ngx_processes[i].name); continue; } live = 1; continue; } if (ngx_processes[i].pid == ngx_new_binary) { ngx_new_binary = 0; if (ngx_noaccepting) { ngx_restart = 1; ngx_noaccepting = 0; } } if (i == ngx_last_process - 1) { ngx_last_process--; } else { ngx_processes[i].pid = -1; } } else if (ngx_processes[i].exiting || !ngx_processes[i].detached) { live = 1; } } return live; }
static ngx_uint_t ngx_reap_worker(ngx_cycle_t *cycle, HANDLE h) { u_long code; ngx_int_t n; for (n = 0; n < ngx_last_process; n++) { if (ngx_processes[n].handle != h) { continue; } if (GetExitCodeProcess(h, &code) == 0) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "GetExitCodeProcess(%P) failed", ngx_processes[n].pid); } ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "%s process %P exited with code %Xul", ngx_processes[n].name, ngx_processes[n].pid, code); ngx_close_handle(ngx_processes[n].reopen); ngx_close_handle(ngx_processes[n].quit); ngx_close_handle(ngx_processes[n].term); ngx_close_handle(h); ngx_processes[n].handle = NULL; ngx_processes[n].term = NULL; ngx_processes[n].quit = NULL; ngx_processes[n].reopen = NULL; if (!ngx_processes[n].exiting && !ngx_terminate && !ngx_quit) { if (ngx_spawn_process(cycle, ngx_processes[n].name, n) == NGX_INVALID_PID) { ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "could not respawn %s", ngx_processes[n].name); if (n == ngx_last_process - 1) { ngx_last_process--; } } } goto found; } ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "unknown process handle %p", h); found: for (n = 0; n < ngx_last_process; n++) { ngx_log_debug5(NGX_LOG_DEBUG_CORE, cycle->log, 0, "process: %d %P %p e:%d j:%d", n, ngx_processes[n].pid, ngx_processes[n].handle, ngx_processes[n].exiting, ngx_processes[n].just_spawn); if (ngx_processes[n].handle) { return 1; } } return 0; }
ngx_int_t ngx_procs_start(ngx_cycle_t *cycle, ngx_int_t type) { ngx_int_t rc, respawn; ngx_uint_t i, p, n; ngx_channel_t ch; ngx_proc_args_t **args; ngx_proc_conf_t **cpcfp; ngx_proc_module_t *module; ngx_proc_main_conf_t *cmcf; ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "start procs processes"); if (ngx_get_conf(cycle->conf_ctx, ngx_procs_module) == NULL) { return NGX_OK; } ch.command = NGX_CMD_OPEN_CHANNEL; cmcf = ngx_proc_get_main_conf(cycle->conf_ctx, ngx_proc_core_module); cpcfp = cmcf->processes.elts; args = ngx_pcalloc(cycle->pool, sizeof(ngx_proc_args_t *) * cmcf->processes.nelts); if (args == NULL) { return NGX_ERROR; } for (p = 0; p< cmcf->processes.nelts; p++) { args[p] = ngx_pcalloc(cycle->pool, sizeof(ngx_proc_args_t)); if (args[p] == NULL) { return NGX_ERROR; } } respawn = type ? NGX_PROCESS_JUST_RESPAWN : NGX_PROCESS_RESPAWN; for (i = 0; ngx_modules[i]; i++) { if (ngx_modules[i]->type != NGX_PROC_MODULE) { continue; } module = ngx_modules[i]->ctx; for (p = 0; p < cmcf->processes.nelts; p++) { if (ngx_strcmp(cpcfp[p]->name.data, module->name.data) == 0) { if (module->prepare) { rc = module->prepare(cycle); if (rc != NGX_OK) { break; } } if (type == 1) { if (cpcfp[p]->respawn) { respawn = NGX_PROCESS_JUST_RESPAWN; } } else { if (cpcfp[p]->respawn) { respawn = NGX_PROCESS_RESPAWN; } else { respawn = NGX_PROCESS_NORESPAWN; } } /* processes count */ for (n = 0; n < cpcfp[p]->count; n++) { args[p]->module = ngx_modules[i]; args[p]->proc_conf = cpcfp[p]; ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "start process %V", &cpcfp[p]->name); ngx_spawn_process(cycle, ngx_procs_cycle, args[p], (char *) cpcfp[p]->name.data, respawn); ch.pid = ngx_processes[ngx_process_slot].pid; ch.slot = ngx_process_slot; ch.fd = ngx_processes[ngx_process_slot].channel[0]; ngx_procs_pass_open_channel(cycle, &ch); } } } } return NGX_OK; }