blob: f1315c8759fc0b1057c522a2f656dd3284bb4f29 [file] [log] [blame]
Igor Sysoev6de5c2c2002-08-06 16:39:45 +00001
Igor Sysoev6de5c2c2002-08-06 16:39:45 +00002#include <ngx_config.h>
Igor Sysoevb2620632003-01-10 06:09:20 +00003#include <ngx_core.h>
Igor Sysoev239baac2003-06-11 15:28:34 +00004#include <ngx_event.h>
Igor Sysoevaa3436c2003-05-30 14:27:59 +00005#include <nginx.h>
Igor Sysoev6de5c2c2002-08-06 16:39:45 +00006
7
Igor Sysoevf0677992004-01-08 17:08:10 +00008typedef struct {
Igor Sysoevd8e1f072004-01-22 06:47:28 +00009 ngx_flag_t daemon;
10 ngx_flag_t master;
11 ngx_flag_t worker_reopen;
12 uid_t user;
13 gid_t group;
14 ngx_str_t pid;
15 ngx_str_t newpid;
Igor Sysoevf0677992004-01-08 17:08:10 +000016} ngx_core_conf_t;
17
18
19typedef struct {
20 ngx_file_t pid;
Igor Sysoev80340f02004-01-13 21:33:59 +000021 char *name;
Igor Sysoevf0677992004-01-08 17:08:10 +000022 char *const *argv;
23} ngx_master_ctx_t;
24
25
26static void ngx_master_process_cycle(ngx_cycle_t *cycle, ngx_master_ctx_t *ctx);
Igor Sysoevf20c05f2004-01-16 18:29:15 +000027static void ngx_master_exit(ngx_cycle_t *cycle, ngx_master_ctx_t *ctx);
Igor Sysoev3c3ca172004-01-05 20:55:48 +000028static void ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data);
Igor Sysoeva9030eb2004-01-06 16:49:34 +000029static ngx_int_t ngx_add_inherited_sockets(ngx_cycle_t *cycle, char **envp);
Igor Sysoev80340f02004-01-13 21:33:59 +000030static ngx_pid_t ngx_exec_new_binary(ngx_cycle_t *cycle, char *const *argv);
Igor Sysoev3c3ca172004-01-05 20:55:48 +000031static ngx_int_t ngx_core_module_init(ngx_cycle_t *cycle);
Igor Sysoev03420a62004-01-20 20:40:08 +000032static char *ngx_set_user(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
Igor Sysoev2b542382002-08-20 14:48:28 +000033
Igor Sysoev7f125082003-07-11 15:17:50 +000034
Igor Sysoev7f125082003-07-11 15:17:50 +000035static ngx_str_t core_name = ngx_string("core");
36
37static ngx_command_t ngx_core_commands[] = {
38
Igor Sysoev3c3ca172004-01-05 20:55:48 +000039 { ngx_string("user"),
Igor Sysoev03420a62004-01-20 20:40:08 +000040 NGX_MAIN_CONF|NGX_CONF_TAKE12,
41 ngx_set_user,
Igor Sysoev3c3ca172004-01-05 20:55:48 +000042 0,
Igor Sysoev03420a62004-01-20 20:40:08 +000043 0,
Igor Sysoev3c3ca172004-01-05 20:55:48 +000044 NULL },
45
Igor Sysoev2b58fbf2003-12-09 15:08:11 +000046 { ngx_string("daemon"),
47 NGX_MAIN_CONF|NGX_CONF_TAKE1,
48 ngx_conf_set_core_flag_slot,
49 0,
50 offsetof(ngx_core_conf_t, daemon),
51 NULL },
Igor Sysoev7f125082003-07-11 15:17:50 +000052
Igor Sysoevf0677992004-01-08 17:08:10 +000053 { ngx_string("master_process"),
Igor Sysoev3c3ca172004-01-05 20:55:48 +000054 NGX_MAIN_CONF|NGX_CONF_TAKE1,
55 ngx_conf_set_core_flag_slot,
56 0,
Igor Sysoevf0677992004-01-08 17:08:10 +000057 offsetof(ngx_core_conf_t, master),
Igor Sysoev3c3ca172004-01-05 20:55:48 +000058 NULL },
59
Igor Sysoevd8e1f072004-01-22 06:47:28 +000060 { ngx_string("worker_reopen"),
61 NGX_MAIN_CONF|NGX_CONF_TAKE1,
62 ngx_conf_set_core_flag_slot,
63 0,
64 offsetof(ngx_core_conf_t, worker_reopen),
65 NULL },
66
Igor Sysoev2b58fbf2003-12-09 15:08:11 +000067 ngx_null_command
Igor Sysoev7f125082003-07-11 15:17:50 +000068};
69
70
71ngx_module_t ngx_core_module = {
72 NGX_MODULE,
73 &core_name, /* module context */
74 ngx_core_commands, /* module directives */
75 NGX_CORE_MODULE, /* module type */
Igor Sysoev3c3ca172004-01-05 20:55:48 +000076 ngx_core_module_init, /* init module */
Igor Sysoev7f125082003-07-11 15:17:50 +000077 NULL /* init child */
78};
79
80
Igor Sysoev03420a62004-01-20 20:40:08 +000081ngx_int_t ngx_max_module;
82ngx_uint_t ngx_connection_counter;
Igor Sysoeva9830112003-05-19 16:39:14 +000083
Igor Sysoev03420a62004-01-20 20:40:08 +000084ngx_int_t ngx_process;
85ngx_pid_t ngx_new_binary;
Igor Sysoeva8fa0a62003-11-25 20:44:56 +000086
Igor Sysoev03420a62004-01-20 20:40:08 +000087ngx_int_t ngx_inherited;
88ngx_int_t ngx_signal;
89ngx_int_t ngx_reap;
90ngx_int_t ngx_terminate;
91ngx_int_t ngx_quit;
92ngx_int_t ngx_noaccept;
93ngx_int_t ngx_reconfigure;
94ngx_int_t ngx_reopen;
95ngx_int_t ngx_change_binary;
Igor Sysoev3c3ca172004-01-05 20:55:48 +000096
97
98int main(int argc, char *const *argv, char **envp)
Igor Sysoev6abfde62003-07-01 15:00:03 +000099{
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000100 ngx_fd_t fd;
101 ngx_int_t i;
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000102 ngx_log_t *log;
103 ngx_cycle_t *cycle, init_cycle;
104 ngx_open_file_t *file;
105 ngx_core_conf_t *ccf;
Igor Sysoevf0677992004-01-08 17:08:10 +0000106 ngx_master_ctx_t ctx;
Igor Sysoev562e53e2003-11-13 06:14:05 +0000107#if !(WIN32)
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000108 size_t len;
109 char pid[/* STUB */ 10];
Igor Sysoev562e53e2003-11-13 06:14:05 +0000110#endif
Igor Sysoev6abfde62003-07-01 15:00:03 +0000111
Igor Sysoev62260f22003-12-05 17:07:27 +0000112#if __FreeBSD__
113 ngx_debug_init();
Igor Sysoev9d639522003-07-07 06:11:50 +0000114#endif
115
Igor Sysoevbc5c2872003-07-02 05:01:53 +0000116 /* TODO */ ngx_max_sockets = -1;
Igor Sysoev6abfde62003-07-01 15:00:03 +0000117
Igor Sysoeva8fa0a62003-11-25 20:44:56 +0000118 ngx_time_init();
Igor Sysoevf0677992004-01-08 17:08:10 +0000119
Igor Sysoeve89c4582003-12-19 08:15:11 +0000120#if (HAVE_PCRE)
Igor Sysoeva8fa0a62003-11-25 20:44:56 +0000121 ngx_regex_init();
Igor Sysoeve89c4582003-12-19 08:15:11 +0000122#endif
Igor Sysoev562e53e2003-11-13 06:14:05 +0000123
Igor Sysoev6abfde62003-07-01 15:00:03 +0000124 log = ngx_log_init_errlog();
125
Igor Sysoeve89c4582003-12-19 08:15:11 +0000126 /* init_cycle->log is required for signal handlers */
127
128 ngx_memzero(&init_cycle, sizeof(ngx_cycle_t));
129 init_cycle.log = log;
130 ngx_cycle = &init_cycle;
131
Igor Sysoev6abfde62003-07-01 15:00:03 +0000132 if (ngx_os_init(log) == NGX_ERROR) {
133 return 1;
134 }
135
136 ngx_max_module = 0;
137 for (i = 0; ngx_modules[i]; i++) {
138 ngx_modules[i]->index = ngx_max_module++;
139 }
140
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000141 if (!(init_cycle.pool = ngx_create_pool(1024, log))) {
142 return 1;
143 }
144
Igor Sysoeva9030eb2004-01-06 16:49:34 +0000145 if (ngx_add_inherited_sockets(&init_cycle, envp) == NGX_ERROR) {
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000146 return 1;
147 }
148
149 cycle = ngx_init_cycle(&init_cycle);
Igor Sysoevbc5c2872003-07-02 05:01:53 +0000150 if (cycle == NULL) {
Igor Sysoev6abfde62003-07-01 15:00:03 +0000151 return 1;
152 }
153
Igor Sysoev9d639522003-07-07 06:11:50 +0000154 ngx_cycle = cycle;
Igor Sysoev340b03b2003-07-04 15:10:33 +0000155
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000156 ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
157
Igor Sysoevf0677992004-01-08 17:08:10 +0000158 ngx_process = (ccf->master != 0) ? NGX_PROCESS_MASTER : NGX_PROCESS_SINGLE;
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000159
Igor Sysoev3d58f8c2004-01-08 08:47:17 +0000160#if (WIN32)
161
162#if 0
163
164 if (run_as_service) {
165 if (ngx_servie(cycle->log) == NGX_ERROR) {
166 return 1;
167 }
168
169 return 0;
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000170 }
171
Igor Sysoev3d58f8c2004-01-08 08:47:17 +0000172#endif
173
174#else
Igor Sysoevb8c367c2003-07-10 16:26:57 +0000175
Igor Sysoev7f125082003-07-11 15:17:50 +0000176 if (ccf->daemon != 0) {
Igor Sysoev160d7742003-11-19 16:26:41 +0000177 if (ngx_daemon(cycle->log) == NGX_ERROR) {
Igor Sysoevb8c367c2003-07-10 16:26:57 +0000178 return 1;
179 }
180 }
181
Igor Sysoev160d7742003-11-19 16:26:41 +0000182 if (dup2(cycle->log->file->fd, STDERR_FILENO) == -1) {
183 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
Igor Sysoev7f125082003-07-11 15:17:50 +0000184 "dup2(STDERR) failed");
Igor Sysoevb8c367c2003-07-10 16:26:57 +0000185 return 1;
186 }
187
Igor Sysoevdc867cd2003-12-14 20:10:27 +0000188 if (ccf->pid.len == 0) {
189 ccf->pid.len = sizeof(NGINX_PID) - 1;
190 ccf->pid.data = NGINX_PID;
Igor Sysoevf2954c32004-01-08 21:02:06 +0000191 ccf->newpid.len = sizeof(NGINX_NEW_PID) - 1;
192 ccf->newpid.data = NGINX_NEW_PID;
Igor Sysoevdc867cd2003-12-14 20:10:27 +0000193 }
194
195 len = ngx_snprintf(pid, /* STUB */ 10, PID_T_FMT, ngx_getpid());
Igor Sysoevf0677992004-01-08 17:08:10 +0000196 ngx_memzero(&ctx.pid, sizeof(ngx_file_t));
Igor Sysoevf2954c32004-01-08 21:02:06 +0000197 ctx.pid.name = ngx_inherited ? ccf->newpid : ccf->pid;
Igor Sysoev80340f02004-01-13 21:33:59 +0000198 ctx.name = ccf->pid.data;
Igor Sysoevdc867cd2003-12-14 20:10:27 +0000199
Igor Sysoevf0677992004-01-08 17:08:10 +0000200 ctx.pid.fd = ngx_open_file(ctx.pid.name.data, NGX_FILE_RDWR,
Igor Sysoevdc867cd2003-12-14 20:10:27 +0000201 NGX_FILE_CREATE_OR_OPEN);
202
Igor Sysoevf0677992004-01-08 17:08:10 +0000203 if (ctx.pid.fd == NGX_INVALID_FILE) {
Igor Sysoevdc867cd2003-12-14 20:10:27 +0000204 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
Igor Sysoevf0677992004-01-08 17:08:10 +0000205 ngx_open_file_n " \"%s\" failed", ctx.pid.name.data);
Igor Sysoevdc867cd2003-12-14 20:10:27 +0000206 return 1;
207 }
208
Igor Sysoevf0677992004-01-08 17:08:10 +0000209 if (ngx_write_file(&ctx.pid, pid, len, 0) == NGX_ERROR) {
Igor Sysoevdc867cd2003-12-14 20:10:27 +0000210 return 1;
211 }
212
Igor Sysoevf0677992004-01-08 17:08:10 +0000213 if (ngx_close_file(ctx.pid.fd) == NGX_FILE_ERROR) {
Igor Sysoevdc867cd2003-12-14 20:10:27 +0000214 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
Igor Sysoevf0677992004-01-08 17:08:10 +0000215 ngx_close_file_n " \"%s\" failed", ctx.pid.name.data);
Igor Sysoevdc867cd2003-12-14 20:10:27 +0000216 }
217
Igor Sysoevb8c367c2003-07-10 16:26:57 +0000218#endif
Igor Sysoev6abfde62003-07-01 15:00:03 +0000219
Igor Sysoevf0677992004-01-08 17:08:10 +0000220 ctx.argv = argv;
221
222 ngx_master_process_cycle(cycle, &ctx);
Igor Sysoev3d58f8c2004-01-08 08:47:17 +0000223
224 return 0;
225}
226
227
Igor Sysoev80340f02004-01-13 21:33:59 +0000228/* TODO: broken single process */
229
Igor Sysoevf0677992004-01-08 17:08:10 +0000230static void ngx_master_process_cycle(ngx_cycle_t *cycle, ngx_master_ctx_t *ctx)
Igor Sysoev3d58f8c2004-01-08 08:47:17 +0000231{
Igor Sysoevd8e1f072004-01-22 06:47:28 +0000232 int signo;
233 char *name;
234 sigset_t set, wset;
235 struct timeval tv;
236 ngx_uint_t i, live, sent;
237 ngx_msec_t delay;
238 ngx_core_conf_t *ccf;
Igor Sysoevf0677992004-01-08 17:08:10 +0000239
Igor Sysoevbaf61e12004-01-09 15:47:42 +0000240 delay = 125;
Igor Sysoevf0677992004-01-08 17:08:10 +0000241
242 sigemptyset(&set);
243 sigaddset(&set, SIGCHLD);
244 sigaddset(&set, ngx_signal_value(NGX_RECONFIGURE_SIGNAL));
245 sigaddset(&set, ngx_signal_value(NGX_REOPEN_SIGNAL));
Igor Sysoev49783fc2004-01-13 16:43:23 +0000246 sigaddset(&set, ngx_signal_value(NGX_NOACCEPT_SIGNAL));
Igor Sysoevf0677992004-01-08 17:08:10 +0000247 sigaddset(&set, ngx_signal_value(NGX_TERMINATE_SIGNAL));
248 sigaddset(&set, ngx_signal_value(NGX_SHUTDOWN_SIGNAL));
249 sigaddset(&set, ngx_signal_value(NGX_CHANGEBIN_SIGNAL));
250
251 sigemptyset(&wset);
252
253 if (sigprocmask(SIG_BLOCK, &set, NULL) == -1) {
254 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
255 "sigprocmask() failed");
256 }
Igor Sysoev6abfde62003-07-01 15:00:03 +0000257
Igor Sysoev49783fc2004-01-13 16:43:23 +0000258 ngx_signal = 0;
Igor Sysoev80340f02004-01-13 21:33:59 +0000259 ngx_new_binary = 0;
Igor Sysoev49783fc2004-01-13 16:43:23 +0000260 signo = 0;
Igor Sysoev0911f772004-01-14 18:19:42 +0000261 sent = 0;
Igor Sysoevf20c05f2004-01-16 18:29:15 +0000262 live = 0;
Igor Sysoev49783fc2004-01-13 16:43:23 +0000263
Igor Sysoev6abfde62003-07-01 15:00:03 +0000264 for ( ;; ) {
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000265 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "new cycle");
Igor Sysoev9d9f58f2003-07-02 18:51:41 +0000266
Igor Sysoev3d58f8c2004-01-08 08:47:17 +0000267 if (ngx_process == NGX_PROCESS_MASTER) {
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000268 ngx_spawn_process(cycle, ngx_worker_process_cycle, NULL,
269 "worker process", NGX_PROCESS_RESPAWN);
Igor Sysoevf20c05f2004-01-16 18:29:15 +0000270 live = 1;
Igor Sysoev160d7742003-11-19 16:26:41 +0000271
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000272 } else {
273 ngx_init_temp_number();
Igor Sysoev160d7742003-11-19 16:26:41 +0000274
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000275 for (i = 0; ngx_modules[i]; i++) {
276 if (ngx_modules[i]->init_process) {
277 if (ngx_modules[i]->init_process(cycle) == NGX_ERROR) {
278 /* fatal */
279 exit(1);
280 }
Igor Sysoev340b03b2003-07-04 15:10:33 +0000281 }
282 }
283 }
Igor Sysoev9d9f58f2003-07-02 18:51:41 +0000284
Igor Sysoevd8e1f072004-01-22 06:47:28 +0000285 ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx,
286 ngx_core_module);
287
Igor Sysoev80340f02004-01-13 21:33:59 +0000288 /* a cycle with the same configuration because a new one is invalid */
Igor Sysoev7349bef2003-07-03 16:30:22 +0000289
Igor Sysoev6abfde62003-07-01 15:00:03 +0000290 for ( ;; ) {
291
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000292 /* an event loop */
293
Igor Sysoev7349bef2003-07-03 16:30:22 +0000294 for ( ;; ) {
Igor Sysoev7349bef2003-07-03 16:30:22 +0000295
Igor Sysoevf0677992004-01-08 17:08:10 +0000296 if (ngx_process == NGX_PROCESS_MASTER) {
Igor Sysoev0911f772004-01-14 18:19:42 +0000297 if (sent) {
298 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
299 "sent signal cycle");
Igor Sysoev7349bef2003-07-03 16:30:22 +0000300
Igor Sysoev49783fc2004-01-13 16:43:23 +0000301 if (sigprocmask(SIG_UNBLOCK, &set, NULL) == -1) {
302 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
303 "sigprocmask() failed");
304 continue;
305 }
Igor Sysoevf0677992004-01-08 17:08:10 +0000306
Igor Sysoev49783fc2004-01-13 16:43:23 +0000307 /*
308 * there is very big chance that the pending signals
309 * would be delivered right on the sigprocmask() return
310 */
311
312 if (!ngx_signal) {
313
314 if (delay < 15000) {
315 delay *= 2;
316 }
317
318 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
319 "msleep %d", delay);
320
321 ngx_msleep(delay);
322
323 ngx_gettimeofday(&tv);
324 ngx_time_update(tv.tv_sec);
325
326 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
327 "wake up");
328 }
329
330 if (sigprocmask(SIG_BLOCK, &set, NULL) == -1) {
331 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
332 "sigprocmask() failed");
333 }
334
335 ngx_signal = 0;
336
337 } else {
Igor Sysoev80340f02004-01-13 21:33:59 +0000338 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
339 "sigsuspend");
340
Igor Sysoev49783fc2004-01-13 16:43:23 +0000341 sigsuspend(&wset);
342
343 ngx_gettimeofday(&tv);
344 ngx_time_update(tv.tv_sec);
Igor Sysoev80340f02004-01-13 21:33:59 +0000345
346 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
347 "wake up");
Igor Sysoev49783fc2004-01-13 16:43:23 +0000348 }
349
Igor Sysoev80340f02004-01-13 21:33:59 +0000350 } else { /* NGX_PROCESS_SINGLE */
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000351 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
352 "worker cycle");
353
354 ngx_process_events(cycle->log);
Igor Sysoevd8e1f072004-01-22 06:47:28 +0000355 live = 0;
Igor Sysoev49783fc2004-01-13 16:43:23 +0000356 }
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000357
Igor Sysoev49783fc2004-01-13 16:43:23 +0000358 if (ngx_reap) {
Igor Sysoevd8e1f072004-01-22 06:47:28 +0000359 ngx_reap = 0;
Igor Sysoev80340f02004-01-13 21:33:59 +0000360 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
Igor Sysoevd8e1f072004-01-22 06:47:28 +0000361
Igor Sysoev80340f02004-01-13 21:33:59 +0000362 "reap childs");
363
Igor Sysoev49783fc2004-01-13 16:43:23 +0000364 live = 0;
365 for (i = 0; i < ngx_last_process; i++) {
Igor Sysoev80340f02004-01-13 21:33:59 +0000366
Igor Sysoev0911f772004-01-14 18:19:42 +0000367 ngx_log_debug6(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
368 "child: " PID_T_FMT
369 " s:%d e:%d t:%d d:%d r:%d",
370 ngx_processes[i].pid,
371 ngx_processes[i].signal,
372 ngx_processes[i].exiting,
373 ngx_processes[i].exited,
374 ngx_processes[i].detached,
375 ngx_processes[i].respawn);
Igor Sysoev993dc062004-01-13 06:39:14 +0000376
Igor Sysoev80340f02004-01-13 21:33:59 +0000377 if (ngx_processes[i].exited) {
Igor Sysoev0911f772004-01-14 18:19:42 +0000378
379 if (ngx_processes[i].respawn
380 && !ngx_processes[i].exiting
381 && !ngx_terminate
382 && !ngx_quit)
383 {
384 if (ngx_spawn_process(cycle,
385 ngx_processes[i].proc,
386 ngx_processes[i].data,
387 ngx_processes[i].name, i)
388 == NGX_ERROR)
389 {
390 ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
391 "can not respawn %s",
392 ngx_processes[i].name);
393 }
394
395 continue;
396 }
397
Igor Sysoev80340f02004-01-13 21:33:59 +0000398 if (ngx_processes[i].pid == ngx_new_binary) {
399 ngx_new_binary = 0;
400 }
401
402 if (i != --ngx_last_process) {
403 ngx_processes[i--] =
Igor Sysoevf2954c32004-01-08 21:02:06 +0000404 ngx_processes[ngx_last_process];
Igor Sysoev80340f02004-01-13 21:33:59 +0000405 }
Igor Sysoev0911f772004-01-14 18:19:42 +0000406
407 } else if (!ngx_processes[i].detached
408 && (ngx_terminate || ngx_quit))
409 {
410 live = 1;
411
412 } else if (ngx_processes[i].exiting) {
413 live = 1;
Igor Sysoevf2954c32004-01-08 21:02:06 +0000414 }
Igor Sysoev49783fc2004-01-13 16:43:23 +0000415 }
Igor Sysoevf2954c32004-01-08 21:02:06 +0000416
Igor Sysoev49783fc2004-01-13 16:43:23 +0000417 if (!live) {
Igor Sysoevf20c05f2004-01-16 18:29:15 +0000418 sent = 0;
Igor Sysoevf2954c32004-01-08 21:02:06 +0000419 }
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000420 }
421
Igor Sysoevf20c05f2004-01-16 18:29:15 +0000422 if (!live && (ngx_terminate || ngx_quit)) {
423 ngx_master_exit(cycle, ctx);
424 }
425
Igor Sysoevf2954c32004-01-08 21:02:06 +0000426 if (ngx_terminate) {
Igor Sysoevbaf61e12004-01-09 15:47:42 +0000427 if (delay > 10000) {
Igor Sysoev993dc062004-01-13 06:39:14 +0000428 signo = SIGKILL;
Igor Sysoevbaf61e12004-01-09 15:47:42 +0000429 } else {
Igor Sysoev993dc062004-01-13 06:39:14 +0000430 signo = ngx_signal_value(NGX_TERMINATE_SIGNAL);
Igor Sysoevbaf61e12004-01-09 15:47:42 +0000431 }
Igor Sysoevdc867cd2003-12-14 20:10:27 +0000432
Igor Sysoev49783fc2004-01-13 16:43:23 +0000433 } else if (ngx_quit) {
Igor Sysoev993dc062004-01-13 06:39:14 +0000434 signo = ngx_signal_value(NGX_SHUTDOWN_SIGNAL);
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000435
Igor Sysoev49783fc2004-01-13 16:43:23 +0000436 } else {
Igor Sysoevdc867cd2003-12-14 20:10:27 +0000437
Igor Sysoev49783fc2004-01-13 16:43:23 +0000438 if (ngx_noaccept) {
Igor Sysoev49783fc2004-01-13 16:43:23 +0000439 signo = ngx_signal_value(NGX_SHUTDOWN_SIGNAL);
440 }
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000441
Igor Sysoev49783fc2004-01-13 16:43:23 +0000442 if (ngx_change_binary) {
443 ngx_change_binary = 0;
444 ngx_log_error(NGX_LOG_INFO, cycle->log, 0,
445 "changing binary");
Igor Sysoev80340f02004-01-13 21:33:59 +0000446 ngx_new_binary = ngx_exec_new_binary(cycle, ctx->argv);
Igor Sysoev49783fc2004-01-13 16:43:23 +0000447 }
Igor Sysoev7349bef2003-07-03 16:30:22 +0000448
Igor Sysoev49783fc2004-01-13 16:43:23 +0000449 if (ngx_reconfigure) {
Igor Sysoev49783fc2004-01-13 16:43:23 +0000450 signo = ngx_signal_value(NGX_SHUTDOWN_SIGNAL);
451 ngx_log_error(NGX_LOG_INFO, cycle->log, 0,
452 "reconfiguring");
453 }
454
455 if (ngx_reopen) {
Igor Sysoevd8e1f072004-01-22 06:47:28 +0000456 if (ngx_process == NGX_PROCESS_MASTER) {
457 if (ccf->worker_reopen > 0) {
458 signo = ngx_signal_value(NGX_REOPEN_SIGNAL);
459 ngx_reopen = 0;
460 } else {
461 signo = ngx_signal_value(NGX_SHUTDOWN_SIGNAL);
462 }
463
464 } else { /* NGX_PROCESS_SINGLE */
465 ngx_reopen = 0;
466 }
Igor Sysoev80340f02004-01-13 21:33:59 +0000467
Igor Sysoev49783fc2004-01-13 16:43:23 +0000468 ngx_log_error(NGX_LOG_INFO, cycle->log, 0,
469 "reopening logs");
470 ngx_reopen_files(cycle);
471 }
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000472 }
473
Igor Sysoev993dc062004-01-13 06:39:14 +0000474 if (signo) {
Igor Sysoev0911f772004-01-14 18:19:42 +0000475 for (i = 0; i < ngx_last_process; i++) {
Igor Sysoev80340f02004-01-13 21:33:59 +0000476
Igor Sysoev0911f772004-01-14 18:19:42 +0000477 if (!ngx_processes[i].detached) {
478 ngx_processes[i].signal = signo;
479
480 ngx_log_debug2(NGX_LOG_DEBUG_EVENT,
481 cycle->log, 0,
482 "signal " PID_T_FMT " %d",
483 ngx_processes[i].pid, signo);
Igor Sysoevbaf61e12004-01-09 15:47:42 +0000484 }
Igor Sysoev0911f772004-01-14 18:19:42 +0000485 }
486 delay = 125;
487 signo = 0;
488 }
489
490 for (i = 0; i < ngx_last_process; i++) {
491
492 if (ngx_processes[i].signal == 0) {
493 continue;
Igor Sysoevbaf61e12004-01-09 15:47:42 +0000494 }
Igor Sysoev993dc062004-01-13 06:39:14 +0000495
Igor Sysoev0911f772004-01-14 18:19:42 +0000496 ngx_log_debug2(NGX_LOG_DEBUG_CORE, cycle->log, 0,
497 "kill (" PID_T_FMT ", %d)" ,
498 ngx_processes[i].pid,
499 ngx_processes[i].signal);
500
501 if (kill(ngx_processes[i].pid, ngx_processes[i].signal)
502 == -1)
503 {
504 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
505 "kill(%d, %d) failed",
506 ngx_processes[i].pid,
507 ngx_processes[i].signal);
508 continue;
509 }
510
511 if (ngx_processes[i].signal
512 != ngx_signal_value(NGX_REOPEN_SIGNAL))
513 {
Igor Sysoevd8e1f072004-01-22 06:47:28 +0000514 sent = 1;
Igor Sysoev0911f772004-01-14 18:19:42 +0000515 ngx_processes[i].exiting = 1;
516 }
Igor Sysoevbaf61e12004-01-09 15:47:42 +0000517 }
518
Igor Sysoevd8e1f072004-01-22 06:47:28 +0000519 if (ngx_reopen || ngx_reconfigure) {
Igor Sysoev993dc062004-01-13 06:39:14 +0000520 break;
521 }
Igor Sysoev7349bef2003-07-03 16:30:22 +0000522 }
Igor Sysoev6abfde62003-07-01 15:00:03 +0000523
Igor Sysoevf20c05f2004-01-16 18:29:15 +0000524 if (ngx_reopen) {
525 ngx_reopen = 0;
526
527 } else if (ngx_noaccept) {
Igor Sysoev49783fc2004-01-13 16:43:23 +0000528 ngx_noaccept = 0;
Igor Sysoevd8e1f072004-01-22 06:47:28 +0000529 ngx_reconfigure = 0;
Igor Sysoevf2954c32004-01-08 21:02:06 +0000530
531 } else {
532 cycle = ngx_init_cycle(cycle);
533 if (cycle == NULL) {
534 cycle = (ngx_cycle_t *) ngx_cycle;
535 continue;
536 }
537
538 ngx_cycle = cycle;
Igor Sysoevd8e1f072004-01-22 06:47:28 +0000539 ngx_reconfigure = 0;
Igor Sysoev6abfde62003-07-01 15:00:03 +0000540 }
541
Igor Sysoev6abfde62003-07-01 15:00:03 +0000542 break;
543 }
544 }
Igor Sysoev6abfde62003-07-01 15:00:03 +0000545}
546
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000547
Igor Sysoevf20c05f2004-01-16 18:29:15 +0000548static void ngx_master_exit(ngx_cycle_t *cycle, ngx_master_ctx_t *ctx)
549{
550 char *name;
551
552 if (ngx_inherited && getppid() > 1) {
553 name = ctx->pid.name.data;
554
555 } else {
556 name = ctx->name;
557 }
558
559 if (ngx_delete_file(name) == NGX_FILE_ERROR) {
560 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
561 ngx_delete_file_n " \"%s\" failed", name);
562 }
563
564 ngx_log_error(NGX_LOG_INFO, cycle->log, 0, "exit");
565 exit(0);
566}
567
568
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000569static void ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data)
Igor Sysoev9d639522003-07-07 06:11:50 +0000570{
Igor Sysoevf0677992004-01-08 17:08:10 +0000571 sigset_t set;
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000572 ngx_int_t i;
573 ngx_listening_t *ls;
Igor Sysoev03420a62004-01-20 20:40:08 +0000574 ngx_core_conf_t *ccf;
Igor Sysoev9d639522003-07-07 06:11:50 +0000575
Igor Sysoev3d58f8c2004-01-08 08:47:17 +0000576 ngx_process = NGX_PROCESS_WORKER;
Igor Sysoevf2954c32004-01-08 21:02:06 +0000577 ngx_last_process = 0;
Igor Sysoev3d58f8c2004-01-08 08:47:17 +0000578
Igor Sysoev03420a62004-01-20 20:40:08 +0000579 ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
580
581 if (ccf->group != (gid_t) NGX_CONF_UNSET) {
582 if (setuid(ccf->group) == -1) {
583 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
584 "setgid(%d) failed", ccf->group);
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000585 /* fatal */
Igor Sysoev03420a62004-01-20 20:40:08 +0000586 exit(2);
587 }
588 }
589
590 if (ccf->user != (uid_t) NGX_CONF_UNSET && geteuid() == 0) {
591 if (setuid(ccf->user) == -1) {
592 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
593 "setuid(%d) failed", ccf->user);
594 /* fatal */
595 exit(2);
Igor Sysoev9d639522003-07-07 06:11:50 +0000596 }
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000597 }
Igor Sysoev9d639522003-07-07 06:11:50 +0000598
Igor Sysoevf0677992004-01-08 17:08:10 +0000599 sigemptyset(&set);
600
601 if (sigprocmask(SIG_SETMASK, &set, NULL) == -1) {
602 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
603 "sigprocmask() failed");
604 }
605
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000606 ngx_init_temp_number();
Igor Sysoev9d639522003-07-07 06:11:50 +0000607
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000608 /*
609 * disable deleting previous events for the listening sockets because
610 * in the worker processes there are no events at all at this point
611 */
612 ls = cycle->listening.elts;
613 for (i = 0; i < cycle->listening.nelts; i++) {
614 ls[i].remain = 0;
615 }
616
617 for (i = 0; ngx_modules[i]; i++) {
618 if (ngx_modules[i]->init_process) {
619 if (ngx_modules[i]->init_process(cycle) == NGX_ERROR) {
620 /* fatal */
621 exit(1);
Igor Sysoev9d639522003-07-07 06:11:50 +0000622 }
623 }
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000624 }
Igor Sysoev9d639522003-07-07 06:11:50 +0000625
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000626 /* TODO: threads: start ngx_worker_thread_cycle() */
627
628 for ( ;; ) {
629 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "worker cycle");
630
631 ngx_process_events(cycle->log);
632
633 if (ngx_terminate) {
634 ngx_log_error(NGX_LOG_INFO, cycle->log, 0, "exiting");
635 exit(0);
Igor Sysoev9d639522003-07-07 06:11:50 +0000636 }
637
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000638 if (ngx_quit) {
639 ngx_log_error(NGX_LOG_INFO, cycle->log, 0,
640 "gracefully shutdowning");
641 break;
642 }
643
644 if (ngx_reopen) {
645 ngx_log_error(NGX_LOG_INFO, cycle->log, 0, "reopen logs");
646 ngx_reopen_files(cycle);
647 ngx_reopen = 0;
648 }
Igor Sysoev9d639522003-07-07 06:11:50 +0000649 }
650
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000651 ngx_close_listening_sockets(cycle);
Igor Sysoev9d639522003-07-07 06:11:50 +0000652
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000653 for ( ;; ) {
654 if (ngx_event_timer_rbtree == &ngx_event_timer_sentinel) {
655 ngx_log_error(NGX_LOG_INFO, cycle->log, 0, "exiting");
656 exit(0);
657 }
Igor Sysoev9d639522003-07-07 06:11:50 +0000658
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000659 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "worker cycle");
660
661 ngx_process_events(cycle->log);
Igor Sysoev9d639522003-07-07 06:11:50 +0000662 }
663}
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000664
665
Igor Sysoeva9030eb2004-01-06 16:49:34 +0000666static ngx_int_t ngx_add_inherited_sockets(ngx_cycle_t *cycle, char **envp)
667{
668 char *p, *v;
669 ngx_socket_t s;
670 ngx_listening_t *ls;
671
672 for ( /* void */ ; *envp; envp++) {
673 if (ngx_strncmp(*envp, NGINX_VAR, NGINX_VAR_LEN) != 0) {
674 continue;
675 }
676
677 ngx_log_error(NGX_LOG_INFO, cycle->log, 0,
678 "using inherited sockets from \"%s\"", *envp);
679
680 ngx_init_array(cycle->listening, cycle->pool,
681 10, sizeof(ngx_listening_t), NGX_ERROR);
682
683 for (p = *envp + NGINX_VAR_LEN, v = p; *p; p++) {
684 if (*p == ':' || *p == ';') {
685 s = ngx_atoi(v, p - v);
686 if (s == NGX_ERROR) {
687 ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
688 "invalid socket number \"%s\" "
689 "in NGINX enviroment variable, "
690 "ignoring the rest of the variable", v);
691 break;
692 }
693 v = p + 1;
694
695 if (!(ls = ngx_push_array(&cycle->listening))) {
696 return NGX_ERROR;
697 }
698
699 ls->fd = s;
700 }
701 }
702
Igor Sysoevf2954c32004-01-08 21:02:06 +0000703 ngx_inherited = 1;
704
Igor Sysoeva9030eb2004-01-06 16:49:34 +0000705 return ngx_set_inherited_sockets(cycle);
706 }
707
708 return NGX_OK;
709}
710
711
Igor Sysoev80340f02004-01-13 21:33:59 +0000712static ngx_pid_t ngx_exec_new_binary(ngx_cycle_t *cycle, char *const *argv)
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000713{
714 char *env[2], *var, *p;
715 ngx_int_t i;
Igor Sysoev80340f02004-01-13 21:33:59 +0000716 ngx_pid_t pid;
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000717 ngx_exec_ctx_t ctx;
718 ngx_listening_t *ls;
719
720 ctx.path = argv[0];
721 ctx.name = "new binary process";
722 ctx.argv = argv;
723
724 var = ngx_alloc(NGINX_VAR_LEN
725 + cycle->listening.nelts * (NGX_INT32_LEN + 1) + 1,
726 cycle->log);
727
728 p = ngx_cpymem(var, NGINX_VAR, NGINX_VAR_LEN);
729
730 ls = cycle->listening.elts;
731 for (i = 0; i < cycle->listening.nelts; i++) {
732 p += ngx_snprintf(p, NGX_INT32_LEN + 2, "%u;", ls[i].fd);
733 }
734
735 env[0] = var;
736 env[1] = NULL;
737 ctx.envp = (char *const *) &env;
738
Igor Sysoev80340f02004-01-13 21:33:59 +0000739 pid = ngx_exec(cycle, &ctx);
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000740
741 ngx_free(var);
Igor Sysoev80340f02004-01-13 21:33:59 +0000742
743 return pid;
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000744}
745
746
747static ngx_int_t ngx_core_module_init(ngx_cycle_t *cycle)
748{
749 ngx_core_conf_t *ccf;
750
751 /*
752 * ngx_core_module has a special init procedure: it is called by
753 * ngx_init_cycle() before the configuration file parsing to create
754 * ngx_core_module configuration and to set its default parameters
755 */
756
757 if (((void **)(cycle->conf_ctx))[ngx_core_module.index] != NULL) {
758 return NGX_OK;
759 }
760
761 if (!(ccf = ngx_pcalloc(cycle->pool, sizeof(ngx_core_conf_t)))) {
762 return NGX_ERROR;
763 }
764 /* set by pcalloc()
765 *
766 * ccf->pid = NULL;
767 */
Igor Sysoev03420a62004-01-20 20:40:08 +0000768 ccf->daemon = NGX_CONF_UNSET;
769 ccf->master = NGX_CONF_UNSET;
Igor Sysoevd8e1f072004-01-22 06:47:28 +0000770 ccf->worker_reopen = NGX_CONF_UNSET;
Igor Sysoev03420a62004-01-20 20:40:08 +0000771 ccf->user = (uid_t) NGX_CONF_UNSET;
772 ccf->group = (gid_t) NGX_CONF_UNSET;
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000773
774 ((void **)(cycle->conf_ctx))[ngx_core_module.index] = ccf;
775
776 return NGX_OK;
777}
Igor Sysoev03420a62004-01-20 20:40:08 +0000778
779
780static char *ngx_set_user(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
781{
782 struct passwd *pwd;
783 struct group *grp;
784 ngx_str_t *value;
785 ngx_core_conf_t *ccf;
786
787 ccf = *(void **)conf;
788
789 if (ccf->user != (uid_t) NGX_CONF_UNSET) {
790 return "is duplicate";
791 }
792
793 value = (ngx_str_t *) cf->args->elts;
794
795 pwd = getpwnam(value[1].data);
796 if (pwd == NULL) {
797 ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno,
798 "getpwnam(%s) failed", value[1].data);
799 return NGX_CONF_ERROR;
800 }
801
802 ccf->user = pwd->pw_uid;
803
804 if (cf->args->nelts == 2) {
805 return NGX_CONF_OK;
806 }
807
808 grp = getgrnam(value[2].data);
809 if (grp == NULL) {
810 ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno,
811 "getgrnam(%s) failed", value[1].data);
812 return NGX_CONF_ERROR;
813 }
814
815 ccf->group = grp->gr_gid;
816
817 return NGX_CONF_OK;
818}