comparison src/core/nginx.c @ 218:05592fd7a436

nginx-0.0.1-2004-01-05-23:55:48 import
author Igor Sysoev <igor@sysoev.ru>
date Mon, 05 Jan 2004 20:55:48 +0000
parents c5d1cdcb04ec
children f57597ec5249
comparison
equal deleted inserted replaced
217:c5d1cdcb04ec 218:05592fd7a436
3 #include <ngx_core.h> 3 #include <ngx_core.h>
4 #include <ngx_event.h> 4 #include <ngx_event.h>
5 #include <nginx.h> 5 #include <nginx.h>
6 6
7 7
8 /* STUB */ 8 static void ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data);
9 void stub_init(ngx_cycle_t *cycle); 9 static void ngx_exec_new_binary(ngx_cycle_t *cycle, char *const *argv);
10 10 static ngx_int_t ngx_core_module_init(ngx_cycle_t *cycle);
11
12
13 static ngx_cycle_t *ngx_init_cycle(ngx_cycle_t *old_cycle, ngx_log_t *log);
14 static int ngx_open_listening_sockets(ngx_cycle_t *cycle, ngx_log_t *log);
15 static void ngx_clean_old_cycles(ngx_event_t *ev);
16 11
17 12
18 typedef struct { 13 typedef struct {
14 ngx_str_t user;
19 int daemon; 15 int daemon;
16 int single;
20 ngx_str_t pid; 17 ngx_str_t pid;
21 } ngx_core_conf_t; 18 } ngx_core_conf_t;
22 19
23 20
24 static ngx_str_t core_name = ngx_string("core"); 21 static ngx_str_t core_name = ngx_string("core");
25 22
26 static ngx_command_t ngx_core_commands[] = { 23 static ngx_command_t ngx_core_commands[] = {
24
25 { ngx_string("user"),
26 NGX_MAIN_CONF|NGX_CONF_TAKE1,
27 ngx_conf_set_core_str_slot,
28 0,
29 offsetof(ngx_core_conf_t, user),
30 NULL },
27 31
28 { ngx_string("daemon"), 32 { ngx_string("daemon"),
29 NGX_MAIN_CONF|NGX_CONF_TAKE1, 33 NGX_MAIN_CONF|NGX_CONF_TAKE1,
30 ngx_conf_set_core_flag_slot, 34 ngx_conf_set_core_flag_slot,
31 0, 35 0,
32 offsetof(ngx_core_conf_t, daemon), 36 offsetof(ngx_core_conf_t, daemon),
33 NULL }, 37 NULL },
34 38
39 { ngx_string("single_process"),
40 NGX_MAIN_CONF|NGX_CONF_TAKE1,
41 ngx_conf_set_core_flag_slot,
42 0,
43 offsetof(ngx_core_conf_t, single),
44 NULL },
45
35 ngx_null_command 46 ngx_null_command
36 }; 47 };
37 48
38 49
39 ngx_module_t ngx_core_module = { 50 ngx_module_t ngx_core_module = {
40 NGX_MODULE, 51 NGX_MODULE,
41 &core_name, /* module context */ 52 &core_name, /* module context */
42 ngx_core_commands, /* module directives */ 53 ngx_core_commands, /* module directives */
43 NGX_CORE_MODULE, /* module type */ 54 NGX_CORE_MODULE, /* module type */
44 NULL, /* init module */ 55 ngx_core_module_init, /* init module */
45 NULL /* init child */ 56 NULL /* init child */
46 }; 57 };
47 58
48 59
49 int ngx_max_module; 60 ngx_int_t ngx_max_module;
50 ngx_os_io_t ngx_io; 61
51 62
52 volatile ngx_cycle_t *ngx_cycle; 63 /* STUB */
53 ngx_array_t ngx_old_cycles; 64 uid_t user;
54
55 static ngx_pool_t *ngx_temp_pool;
56 static ngx_event_t ngx_cleaner_event;
57
58
59 /* STUB NAME */
60 static ngx_connection_t dumb;
61 65
62 u_int ngx_connection_counter; 66 u_int ngx_connection_counter;
63 67
64 68 ngx_int_t ngx_master;
65 int done; 69 ngx_int_t ngx_single;
66 int restart; 70
67 int rotate; 71
68 72 ngx_int_t ngx_respawn;
69 73 ngx_int_t ngx_terminate;
70 int main(int argc, char *const *argv) 74 ngx_int_t ngx_quit;
75 ngx_int_t ngx_reconfigure;
76 ngx_int_t ngx_reopen;
77 ngx_int_t ngx_change_binary;
78
79
80 int main(int argc, char *const *argv, char **envp)
71 { 81 {
72 int i; 82 struct timeval tv;
73 ngx_fd_t fd; 83 ngx_fd_t fd;
74 ngx_log_t *log; 84 ngx_int_t i;
75 ngx_cycle_t *cycle, init_cycle; 85 ngx_err_t err;
76 ngx_open_file_t *file; 86 ngx_log_t *log;
87 ngx_cycle_t *cycle, init_cycle;
88 ngx_open_file_t *file;
89 ngx_core_conf_t *ccf;
77 #if !(WIN32) 90 #if !(WIN32)
78 size_t len; 91 size_t len;
79 char pid[/* STUB */ 10]; 92 char pid[/* STUB */ 10];
80 ngx_file_t pidfile; 93 ngx_file_t pidfile;
81 ngx_core_conf_t *ccf; 94 struct passwd *pwd;
82 #endif 95 #endif
83 96
84 #if __FreeBSD__ 97 #if __FreeBSD__
85 ngx_debug_init(); 98 ngx_debug_init();
86 #endif 99 #endif
92 ngx_regex_init(); 105 ngx_regex_init();
93 #endif 106 #endif
94 107
95 log = ngx_log_init_errlog(); 108 log = ngx_log_init_errlog();
96 109
97
98 /* init_cycle->log is required for signal handlers */ 110 /* init_cycle->log is required for signal handlers */
99 111
100 ngx_memzero(&init_cycle, sizeof(ngx_cycle_t)); 112 ngx_memzero(&init_cycle, sizeof(ngx_cycle_t));
101 init_cycle.log = log; 113 init_cycle.log = log;
102 ngx_cycle = &init_cycle; 114 ngx_cycle = &init_cycle;
108 ngx_max_module = 0; 120 ngx_max_module = 0;
109 for (i = 0; ngx_modules[i]; i++) { 121 for (i = 0; ngx_modules[i]; i++) {
110 ngx_modules[i]->index = ngx_max_module++; 122 ngx_modules[i]->index = ngx_max_module++;
111 } 123 }
112 124
113 cycle = ngx_init_cycle(NULL, log); 125 if (!(init_cycle.pool = ngx_create_pool(1024, log))) {
126 return 1;
127 }
128
129 if (ngx_set_inherited_sockets(&init_cycle, envp) == NGX_ERROR) {
130 return 1;
131 }
132
133 cycle = ngx_init_cycle(&init_cycle);
114 if (cycle == NULL) { 134 if (cycle == NULL) {
115 return 1; 135 return 1;
116 } 136 }
117 137
118 ngx_cycle = cycle; 138 ngx_cycle = cycle;
119 139
140 ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
141
142 if (ccf->single == 1) {
143 ngx_master = 0;
144 ngx_single = 1;
145
146 } else {
147 ngx_master = 1;
148 ngx_single = 0;
149 }
150
120 #if !(WIN32) 151 #if !(WIN32)
121 152
122 ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); 153 /* STUB */
154 if (ccf->user.len) {
155 pwd = getpwnam(ccf->user.data);
156 if (pwd == NULL) {
157 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
158 "getpwnam(%s) failed", ccf->user);
159 return 1;
160 }
161
162 user = pwd->pw_uid;
163 }
164 /* */
123 165
124 if (ccf->daemon != 0) { 166 if (ccf->daemon != 0) {
125 if (ngx_daemon(cycle->log) == NGX_ERROR) { 167 if (ngx_daemon(cycle->log) == NGX_ERROR) {
126 return 1; 168 return 1;
127 } 169 }
160 ngx_close_file_n " \"%s\" failed", pidfile.name.data); 202 ngx_close_file_n " \"%s\" failed", pidfile.name.data);
161 } 203 }
162 204
163 #endif 205 #endif
164 206
165 /* life cycle */ 207 /* a life cycle */
166 208
167 for ( ;; ) { 209 for ( ;; ) {
210 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "new cycle");
211
212 if (ngx_master) {
213 ngx_spawn_process(cycle, ngx_worker_process_cycle, NULL,
214 "worker process", NGX_PROCESS_RESPAWN);
215
216 } else {
217 ngx_init_temp_number();
218
219 for (i = 0; ngx_modules[i]; i++) {
220 if (ngx_modules[i]->init_process) {
221 if (ngx_modules[i]->init_process(cycle) == NGX_ERROR) {
222 /* fatal */
223 exit(1);
224 }
225 }
226 }
227 }
228
168 #if 0 229 #if 0
169 /* STUB */ cycle->log->log_level = NGX_LOG_DEBUG|NGX_LOG_DEBUG_HTTP; 230 reconfigure = 0;
231 reopen = 0;
170 #endif 232 #endif
171 233
172 #if 0 234 /* a cycle with the same configuration */
173
174 #if !(WIN32)
175 ngx_spawn_process(cycle->log);
176 #endif
177
178 stub_init(cycle);
179 #endif
180
181 /* TODO: forks */
182
183 ngx_init_temp_number();
184
185 for (i = 0; ngx_modules[i]; i++) {
186 if (ngx_modules[i]->init_child) {
187 if (ngx_modules[i]->init_child(cycle) == NGX_ERROR) {
188 /* fatal */
189 exit(1);
190 }
191 }
192 }
193
194 /* TODO: threads */
195
196 restart = 0;
197 rotate = 0;
198 235
199 for ( ;; ) { 236 for ( ;; ) {
200 237
238 /* an event loop */
239
201 for ( ;; ) { 240 for ( ;; ) {
202 ngx_log_debug(cycle->log, "worker cycle"); 241
203 242 err = 0;
204 ngx_process_events(cycle->log); 243
205 244 if (ngx_single) {
206 if (done) { 245 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
246 "worker cycle");
247
248 ngx_process_events(cycle->log);
249
250 } else {
251 ngx_set_errno(0);
252 ngx_msleep(1000);
253 err = ngx_errno;
254
255 ngx_gettimeofday(&tv);
256 ngx_time_update(tv.tv_sec);
257
258 if (err) {
259 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, err,
260 "sleep() exited");
261 }
262 }
263
264 if (ngx_quit || ngx_terminate) {
207 #if !(WIN32) 265 #if !(WIN32)
208 if (ngx_delete_file(pidfile.name.data) == NGX_FILE_ERROR) { 266 if (ngx_delete_file(pidfile.name.data) == NGX_FILE_ERROR) {
209 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, 267 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
210 ngx_delete_file_n " \"%s\" failed", 268 ngx_delete_file_n " \"%s\" failed",
211 pidfile.name.data); 269 pidfile.name.data);
212 } 270 }
213 #endif 271 #endif
214 272
215 ngx_log_error(NGX_LOG_INFO, 273 ngx_log_error(NGX_LOG_INFO, cycle->log, 0, "exiting");
216 cycle->log, 0, "exiting"); 274
275 if (ngx_master) {
276 ngx_signal_processes(cycle,
277 ngx_signal_value(NGX_SHUTDOWN_SIGNAL));
278
279 /* TODO: wait workers */
280
281 ngx_msleep(1000);
282
283 ngx_gettimeofday(&tv);
284 ngx_time_update(tv.tv_sec);
285 }
286
287 ngx_log_error(NGX_LOG_INFO, cycle->log, 0, "exit");
217 exit(0); 288 exit(0);
218 } 289 }
219 290
220 if (rotate) { 291 if (err == NGX_EINTR) {
221 ngx_log_error(NGX_LOG_INFO, cycle->log, 0, "reopen logs"); 292 ngx_respawn_processes(cycle);
222 293 }
223 file = cycle->open_files.elts; 294
224 for (i = 0; i < cycle->open_files.nelts; i++) { 295 if (ngx_change_binary) {
225 if (file[i].name.data == NULL) { 296 ngx_change_binary = 0;
226 continue; 297 ngx_log_error(NGX_LOG_INFO, cycle->log, 0,
227 } 298 "changing binary");
228 299 ngx_exec_new_binary(cycle, argv);
229 fd = ngx_open_file(file[i].name.data, 300 /* TODO: quit workers */
230 NGX_FILE_RDWR, 301 }
231 NGX_FILE_CREATE_OR_OPEN|NGX_FILE_APPEND); 302
232 303 if (ngx_reconfigure) {
233 ngx_log_debug(log, "REOPEN: %d:%d:%s" _ fd _ file[i].fd _ file[i].name.data); 304 ngx_log_error(NGX_LOG_INFO, cycle->log, 0, "reconfiguring");
234
235 if (fd == NGX_INVALID_FILE) {
236 ngx_log_error(NGX_LOG_EMERG,
237 cycle->log, ngx_errno,
238 ngx_open_file_n " \"%s\" failed",
239 file[i].name.data);
240 continue;
241 }
242
243 #if (WIN32)
244 if (ngx_file_append_mode(fd) == NGX_ERROR) {
245 ngx_log_error(NGX_LOG_EMERG,
246 cycle->log, ngx_errno,
247 ngx_file_append_mode_n
248 " \"%s\" failed",
249 file[i].name.data);
250
251 if (ngx_close_file(fd) == NGX_FILE_ERROR) {
252 ngx_log_error(NGX_LOG_EMERG,
253 cycle->log, ngx_errno,
254 ngx_close_file_n " \"%s\" failed",
255 file[i].name.data);
256 }
257
258 continue;
259 }
260 #endif
261
262 if (ngx_close_file(file[i].fd) == NGX_FILE_ERROR) {
263 ngx_log_error(NGX_LOG_EMERG,
264 cycle->log, ngx_errno,
265 ngx_close_file_n " \"%s\" failed",
266 file[i].name.data);
267 }
268
269 file[i].fd = fd;
270 }
271
272 rotate = 0;
273 }
274
275 if (restart) {
276 ngx_log_debug(cycle->log, "restart");
277 break; 305 break;
278 } 306 }
279 307
280 } 308 if (ngx_reopen) {
281 309 ngx_log_error(NGX_LOG_INFO, cycle->log, 0,
282 cycle = ngx_init_cycle(cycle, cycle->log); 310 "reopening logs");
311 ngx_reopen_files(cycle);
312 ngx_reopen = 0;
313 }
314
315 }
316
317 cycle = ngx_init_cycle(cycle);
283 if (cycle == NULL) { 318 if (cycle == NULL) {
284 cycle = (ngx_cycle_t *) ngx_cycle; 319 cycle = (ngx_cycle_t *) ngx_cycle;
285 continue; 320 continue;
286 } 321 }
287 322
288 ngx_cycle = cycle; 323 ngx_cycle = cycle;
324 ngx_reconfigure = 0;
289 break; 325 break;
290 } 326 }
291 } 327 }
292 } 328 }
293 329
294 330 #if 0
295 static ngx_cycle_t *ngx_init_cycle(ngx_cycle_t *old_cycle, ngx_log_t *log) 331
332 static ngx_cycle_t *ngx_init_cycle(ngx_cycle_t *old_cycle)
296 { 333 {
297 int i, n, failed; 334 ngx_int_t i, n, failed;
298 ngx_str_t conf_file; 335 ngx_str_t conf_file;
336 ngx_log_t *log;
299 ngx_conf_t conf; 337 ngx_conf_t conf;
300 ngx_pool_t *pool; 338 ngx_pool_t *pool;
301 ngx_cycle_t *cycle, **old; 339 ngx_cycle_t *cycle, **old;
302 ngx_socket_t fd; 340 ngx_socket_t fd;
303 ngx_core_conf_t *ccf; 341 ngx_core_conf_t *ccf;
304 ngx_open_file_t *file; 342 ngx_open_file_t *file;
305 ngx_listening_t *ls, *nls; 343 ngx_listening_t *ls, *nls;
306 344
345 log = old_cycle->log;
307 346
308 if (!(pool = ngx_create_pool(16 * 1024, log))) { 347 if (!(pool = ngx_create_pool(16 * 1024, log))) {
309 return NULL; 348 return NULL;
310 } 349 }
311 350
316 cycle->pool = pool; 355 cycle->pool = pool;
317 356
318 cycle->old_cycle = old_cycle; 357 cycle->old_cycle = old_cycle;
319 358
320 359
321 n = old_cycle ? old_cycle->pathes.nelts : 10; 360 n = old_cycle->pathes.nelts ? old_cycle->pathes.nelts : 10;
322 if (!(cycle->pathes.elts = ngx_pcalloc(pool, n * sizeof(ngx_path_t *)))) { 361 if (!(cycle->pathes.elts = ngx_pcalloc(pool, n * sizeof(ngx_path_t *)))) {
323 ngx_destroy_pool(pool); 362 ngx_destroy_pool(pool);
324 return NULL; 363 return NULL;
325 } 364 }
326 cycle->pathes.nelts = 0; 365 cycle->pathes.nelts = 0;
327 cycle->pathes.size = sizeof(ngx_path_t *); 366 cycle->pathes.size = sizeof(ngx_path_t *);
328 cycle->pathes.nalloc = n; 367 cycle->pathes.nalloc = n;
329 cycle->pathes.pool = pool; 368 cycle->pathes.pool = pool;
330 369
331 370
332 n = old_cycle ? old_cycle->open_files.nelts : 20; 371 n = old_cycle->open_files.nelts ? old_cycle->open_files.nelts : 20;
333 cycle->open_files.elts = ngx_pcalloc(pool, n * sizeof(ngx_open_file_t)); 372 cycle->open_files.elts = ngx_pcalloc(pool, n * sizeof(ngx_open_file_t));
334 if (cycle->open_files.elts == NULL) { 373 if (cycle->open_files.elts == NULL) {
335 ngx_destroy_pool(pool); 374 ngx_destroy_pool(pool);
336 return NULL; 375 return NULL;
337 } 376 }
345 ngx_destroy_pool(pool); 384 ngx_destroy_pool(pool);
346 return NULL; 385 return NULL;
347 } 386 }
348 387
349 388
350 n = old_cycle ? old_cycle->listening.nelts : 10; 389 n = old_cycle->listening.nelts ? old_cycle->listening.nelts : 10;
351 cycle->listening.elts = ngx_pcalloc(pool, n * sizeof(ngx_listening_t)); 390 cycle->listening.elts = ngx_pcalloc(pool, n * sizeof(ngx_listening_t));
352 if (cycle->listening.elts == NULL) { 391 if (cycle->listening.elts == NULL) {
353 ngx_destroy_pool(pool); 392 ngx_destroy_pool(pool);
354 return NULL; 393 return NULL;
355 } 394 }
373 /* set by pcalloc() 412 /* set by pcalloc()
374 * 413 *
375 * ccf->pid = NULL; 414 * ccf->pid = NULL;
376 */ 415 */
377 ccf->daemon = -1; 416 ccf->daemon = -1;
417 ccf->single = -1;
378 ((void **)(cycle->conf_ctx))[ngx_core_module.index] = ccf; 418 ((void **)(cycle->conf_ctx))[ngx_core_module.index] = ccf;
379 419
380 420
381 ngx_memzero(&conf, sizeof(ngx_conf_t)); 421 ngx_memzero(&conf, sizeof(ngx_conf_t));
382 /* STUB: init array ? */ 422 /* STUB: init array ? */
433 break; 473 break;
434 } 474 }
435 #endif 475 #endif
436 } 476 }
437 477
438 #if 0
439 /* STUB */ cycle->log->log_level = NGX_LOG_DEBUG;
440 #endif
441
442 if (!failed) { 478 if (!failed) {
443 if (old_cycle) { 479 if (old_cycle->listening.nelts) {
444 ls = old_cycle->listening.elts; 480 ls = old_cycle->listening.elts;
445 for (i = 0; i < old_cycle->listening.nelts; i++) { 481 for (i = 0; i < old_cycle->listening.nelts; i++) {
446 ls[i].remain = 0; 482 ls[i].remain = 0;
447 } 483 }
448 484
449 nls = cycle->listening.elts; 485 nls = cycle->listening.elts;
450 for (n = 0; n < cycle->listening.nelts; n++) { 486 for (n = 0; n < cycle->listening.nelts; n++) {
451 for (i = 0; i < old_cycle->listening.nelts; i++) { 487 for (i = 0; i < old_cycle->listening.nelts; i++) {
488 if (ls[i].ignore) {
489 continue;
490 }
491
492 ngx_log_error(NGX_LOG_INFO, log, 0,
493 "%X, %X",
494 *(int *) ls[i].sockaddr,
495 *(int *) nls[n].sockaddr);
496
452 if (ngx_memcmp(nls[n].sockaddr, 497 if (ngx_memcmp(nls[n].sockaddr,
453 ls[i].sockaddr, ls[i].socklen) == 0) 498 ls[i].sockaddr, ls[i].socklen) == 0)
454 { 499 {
455 fd = ls[i].fd; 500 fd = ls[i].fd;
456 #if (WIN32) 501 #if (WIN32)
490 ls[i].new = 1; 535 ls[i].new = 1;
491 } 536 }
492 } 537 }
493 538
494 if (!failed) { 539 if (!failed) {
495 if (ngx_open_listening_sockets(cycle, log) == NGX_ERROR) { 540 if (ngx_open_listening_sockets(cycle) == NGX_ERROR) {
496 failed = 1; 541 failed = 1;
497 } 542 }
498 } 543 }
499 } 544 }
500 545
534 579
535 /* commit the new cycle configuration */ 580 /* commit the new cycle configuration */
536 581
537 pool->log = cycle->log; 582 pool->log = cycle->log;
538 583
539 #if 1
540 /* STUB */ cycle->one_process = 1;
541 #endif
542 584
543 for (i = 0; ngx_modules[i]; i++) { 585 for (i = 0; ngx_modules[i]; i++) {
544 if (ngx_modules[i]->init_module) { 586 if (ngx_modules[i]->init_module) {
545 if (ngx_modules[i]->init_module(cycle) == NGX_ERROR) { 587 if (ngx_modules[i]->init_module(cycle) == NGX_ERROR) {
546 /* fatal */ 588 /* fatal */
547 exit(1); 589 exit(1);
548 } 590 }
549 } 591 }
550 } 592 }
551 593
552 if (old_cycle == NULL) { 594 /* close and delete stuff that lefts from an old cycle */
553 return cycle; 595
554 } 596 /* close the unneeded listening sockets */
555 597
556 ls = old_cycle->listening.elts; 598 ls = old_cycle->listening.elts;
557 for (i = 0; i < old_cycle->listening.nelts; i++) { 599 for (i = 0; i < old_cycle->listening.nelts; i++) {
558 if (ls[i].remain) { 600 if (ls[i].remain) {
559 continue; 601 continue;
564 ngx_close_socket_n " %s failed", 606 ngx_close_socket_n " %s failed",
565 ls[i].addr_text.data); 607 ls[i].addr_text.data);
566 } 608 }
567 } 609 }
568 610
611
612 /* close the unneeded open files */
613
569 file = old_cycle->open_files.elts; 614 file = old_cycle->open_files.elts;
570 for (i = 0; i < old_cycle->open_files.nelts; i++) { 615 for (i = 0; i < old_cycle->open_files.nelts; i++) {
571 if (file[i].fd == NGX_INVALID_FILE) { 616 if (file[i].fd == NGX_INVALID_FILE) {
572 continue; 617 continue;
573 } 618 }
577 ngx_close_file_n " \"%s\" failed", 622 ngx_close_file_n " \"%s\" failed",
578 file[i].name.data); 623 file[i].name.data);
579 } 624 }
580 } 625 }
581 626
582 627 if (old_cycle->connections == NULL) {
583 if (!old_cycle->one_process) { 628 /* an old cycle is an init cycle */
629 ngx_destroy_pool(old_cycle->pool);
630 return cycle;
631 }
632
633 if (master) {
584 ngx_destroy_pool(old_cycle->pool); 634 ngx_destroy_pool(old_cycle->pool);
585 return cycle; 635 return cycle;
586 } 636 }
587 637
588 if (ngx_temp_pool == NULL) { 638 if (ngx_temp_pool == NULL) {
624 } 674 }
625 675
626 return cycle; 676 return cycle;
627 } 677 }
628 678
629 679 #endif
630 static int ngx_open_listening_sockets(ngx_cycle_t *cycle, ngx_log_t *log) 680
681
682 #if 0
683
684 static ngx_int_t ngx_set_inherited_sockets(ngx_cycle_t *cycle, char **envp)
631 { 685 {
632 int times, failed, reuseaddr, i; 686 char *p, *v;
633 ngx_err_t err; 687 ngx_socket_t s;
634 ngx_socket_t s; 688 ngx_listening_t *ls;
635 ngx_listening_t *ls; 689 struct sockaddr_in *addr_in;
636 690
637 reuseaddr = 1; 691 for ( /* void */ ; *envp; envp++) {
638 #if (NGX_SUPPRESS_WARN) 692 if (ngx_strncmp(*envp, NGINX_VAR, NGINX_VAR_LEN) != 0) {
639 failed = 0; 693 continue;
640 #endif 694 }
641 695
642 /* TODO: times configurable */ 696 ngx_log_error(NGX_LOG_INFO, cycle->log, 0,
643 697 "using inherited sockets from \"%s\"", *envp);
644 for (times = 10; times; times--) { 698
645 failed = 0; 699 ngx_init_array(cycle->listening, cycle->pool,
646 700 10, sizeof(ngx_listening_t), NGX_ERROR);
647 /* for each listening socket */ 701
648 702 for (p = *envp + NGINX_VAR_LEN, v = p; *p; p++) {
649 ls = cycle->listening.elts; 703 if (*p == ':' || *p == ';') {
650 for (i = 0; i < cycle->listening.nelts; i++) { 704 s = ngx_atoi(v, p - v);
651 705 if (s == NGX_ERROR) {
652 if (ls[i].fd != -1) { 706 ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
653 continue; 707 "invalid socket number \"%s\" "
654 } 708 "in NGINX enviroment variable, "
655 709 "ignoring the rest of the variable", v);
656 if (ls[i].inherited) { 710 break;
657 711 }
658 /* TODO: close on exit */ 712 v = p + 1;
659 /* TODO: nonblocking */ 713
660 /* TODO: deferred accept */ 714 if (!(ls = ngx_push_array(&cycle->listening))) {
661
662 continue;
663 }
664
665 s = ngx_socket(ls[i].family, ls[i].type, ls[i].protocol,
666 ls[i].flags);
667
668 if (s == -1) {
669 ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
670 ngx_socket_n " %s failed", ls[i].addr_text.data);
671 return NGX_ERROR;
672 }
673
674 #if (WIN32)
675 /*
676 * Winsock assignes a socket number divisible by 4
677 * so to find a connection we divide a socket number by 4.
678 */
679
680 if (s % 4) {
681 ngx_log_error(NGX_LOG_EMERG, ls->log, 0,
682 ngx_socket_n " created socket %d", s);
683 return NGX_ERROR;
684 }
685 #endif
686
687 if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
688 (const void *) &reuseaddr, sizeof(int)) == -1) {
689 ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
690 "setsockopt(SO_REUSEADDR) %s failed",
691 ls[i].addr_text.data);
692 return NGX_ERROR;
693 }
694
695 /* TODO: close on exit */
696
697 if (!(ngx_event_flags & NGX_USE_AIO_EVENT)) {
698 if (ngx_nonblocking(s) == -1) {
699 ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
700 ngx_nonblocking_n " %s failed",
701 ls[i].addr_text.data);
702 return NGX_ERROR; 715 return NGX_ERROR;
703 } 716 }
704 } 717
705 718 ls->fd = s;
706 #if 0 719
707 if (ls[i].nonblocking) { 720 /* AF_INET only */
708 if (ngx_nonblocking(s) == -1) { 721
709 ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, 722 ls->sockaddr = ngx_palloc(cycle->pool,
710 ngx_nonblocking_n " %s failed", 723 sizeof(struct sockaddr_in));
711 ls[i].addr_text.data); 724 if (ls->sockaddr == NULL) {
712 return NGX_ERROR; 725 return NGX_ERROR;
713 } 726 }
714 } 727
715 #endif 728 ls->socklen = sizeof(struct sockaddr_in);
716 729 if (getsockname(s, ls->sockaddr, &ls->socklen) == -1) {
717 if (bind(s, ls[i].sockaddr, ls[i].socklen) == -1) { 730 ngx_log_error(NGX_LOG_CRIT, cycle->log, ngx_socket_errno,
718 err = ngx_socket_errno; 731 "getsockname() of the inherited "
719 ngx_log_error(NGX_LOG_EMERG, log, err, 732 "socket #%d failed", s);
720 "bind() to %s failed", ls[i].addr_text.data); 733 ls->ignore = 1;
721 734 continue;
722 if (err != NGX_EADDRINUSE) 735 }
736
737 addr_in = (struct sockaddr_in *) ls->sockaddr;
738
739 if (addr_in->sin_family != AF_INET) {
740 ngx_log_error(NGX_LOG_CRIT, cycle->log, ngx_socket_errno,
741 "the inherited socket #%d has "
742 "unsupported family", s);
743 ls->ignore = 1;
744 continue;
745 }
746 ls->addr_text_max_len = INET_ADDRSTRLEN;
747
748 ls->addr_text.data = ngx_palloc(cycle->pool,
749 ls->addr_text_max_len);
750 if (ls->addr_text.data == NULL) {
723 return NGX_ERROR; 751 return NGX_ERROR;
724 752 }
725 if (ngx_close_socket(s) == -1) 753
726 ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, 754 addr_in->sin_len = 0;
727 ngx_close_socket_n " %s failed", 755
728 ls[i].addr_text.data); 756 ls->family = addr_in->sin_family;
729 757 ls->addr_text.len = ngx_sock_ntop(ls->family, ls->sockaddr,
730 failed = 1; 758 ls->addr_text.data,
731 continue; 759 ls->addr_text_max_len);
732 } 760 if (ls->addr_text.len == 0) {
733 761 return NGX_ERROR;
734 if (listen(s, ls[i].backlog) == -1) { 762 }
735 ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, 763 }
736 "listen() to %s failed", ls[i].addr_text.data); 764 }
737 return NGX_ERROR; 765
738 } 766 break;
739
740 /* TODO: deferred accept */
741
742 ls[i].fd = s;
743 }
744
745 if (!failed)
746 break;
747
748 /* TODO: delay configurable */
749
750 ngx_log_error(NGX_LOG_NOTICE, log, 0,
751 "try again to bind() after 500ms");
752 ngx_msleep(500);
753 }
754
755 if (failed) {
756 ngx_log_error(NGX_LOG_EMERG, log, 0, "still can not bind()");
757 return NGX_ERROR;
758 } 767 }
759 768
760 return NGX_OK; 769 return NGX_OK;
761 } 770 }
762 771
763 772 #endif
764 static void ngx_clean_old_cycles(ngx_event_t *ev) 773
774
775 static void ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data)
765 { 776 {
766 int i, n, found, live; 777 ngx_int_t i;
767 ngx_log_t *log; 778 ngx_listening_t *ls;
768 ngx_cycle_t **cycle; 779
769 780 if (user) {
770 log = ngx_cycle->log; 781 if (setuid(user) == -1) {
771 ngx_temp_pool->log = log; 782 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
772 783 "setuid() failed");
773 ngx_log_debug(log, "clean old cycles"); 784 /* fatal */
774 785 exit(1);
775 live = 0; 786 }
776 787 }
777 cycle = ngx_old_cycles.elts; 788
778 for (i = 0; i < ngx_old_cycles.nelts; i++) { 789 ngx_init_temp_number();
779 790
780 if (cycle[i] == NULL) { 791 /*
781 continue; 792 * disable deleting previous events for the listening sockets because
782 } 793 * in the worker processes there are no events at all at this point
783 794 */
784 found = 0; 795 ls = cycle->listening.elts;
785 796 for (i = 0; i < cycle->listening.nelts; i++) {
786 for (n = 0; n < cycle[i]->connection_n; n++) { 797 ls[i].remain = 0;
787 if (cycle[i]->connections[n].fd != -1) { 798 }
788 found = 1; 799
789 ngx_log_debug(log, "live fd: %d" _ n); 800 for (i = 0; ngx_modules[i]; i++) {
790 break; 801 if (ngx_modules[i]->init_process) {
791 } 802 if (ngx_modules[i]->init_process(cycle) == NGX_ERROR) {
792 } 803 /* fatal */
793 804 exit(1);
794 if (found) { 805 }
795 live = 1; 806 }
796 continue; 807 }
797 } 808
798 809 /* TODO: threads: start ngx_worker_thread_cycle() */
799 ngx_log_debug(log, "clean old cycle: %d" _ i); 810
800 ngx_destroy_pool(cycle[i]->pool); 811 for ( ;; ) {
801 cycle[i] = NULL; 812 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "worker cycle");
802 } 813
803 814 ngx_process_events(cycle->log);
804 ngx_log_debug(log, "old cycles status: %d" _ live); 815
805 816 if (ngx_terminate) {
806 if (live) { 817 ngx_log_error(NGX_LOG_INFO, cycle->log, 0, "exiting");
807 ngx_log_debug(log, "TIMER"); 818 exit(0);
808 ngx_add_timer(ev, 30000); 819 }
809 820
810 } else { 821 if (ngx_quit) {
811 ngx_destroy_pool(ngx_temp_pool); 822 ngx_log_error(NGX_LOG_INFO, cycle->log, 0,
812 ngx_temp_pool = NULL; 823 "gracefully shutdowning");
813 ngx_old_cycles.nelts = 0; 824 break;
825 }
826
827 if (ngx_reopen) {
828 ngx_log_error(NGX_LOG_INFO, cycle->log, 0, "reopen logs");
829 ngx_reopen_files(cycle);
830 ngx_reopen = 0;
831 }
832 }
833
834 ngx_close_listening_sockets(cycle);
835
836 for ( ;; ) {
837 if (ngx_event_timer_rbtree == &ngx_event_timer_sentinel) {
838 ngx_log_error(NGX_LOG_INFO, cycle->log, 0, "exiting");
839 exit(0);
840 }
841
842 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "worker cycle");
843
844 ngx_process_events(cycle->log);
814 } 845 }
815 } 846 }
847
848
849 static void ngx_exec_new_binary(ngx_cycle_t *cycle, char *const *argv)
850 {
851 char *env[2], *var, *p;
852 ngx_int_t i;
853 ngx_exec_ctx_t ctx;
854 ngx_listening_t *ls;
855
856 ctx.path = argv[0];
857 ctx.name = "new binary process";
858 ctx.argv = argv;
859
860 var = ngx_alloc(NGINX_VAR_LEN
861 + cycle->listening.nelts * (NGX_INT32_LEN + 1) + 1,
862 cycle->log);
863
864 p = ngx_cpymem(var, NGINX_VAR, NGINX_VAR_LEN);
865
866 ls = cycle->listening.elts;
867 for (i = 0; i < cycle->listening.nelts; i++) {
868 p += ngx_snprintf(p, NGX_INT32_LEN + 2, "%u;", ls[i].fd);
869 }
870
871 env[0] = var;
872 env[1] = NULL;
873 ctx.envp = (char *const *) &env;
874
875 ngx_exec(cycle, &ctx);
876
877 ngx_free(var);
878 }
879
880
881 static ngx_int_t ngx_core_module_init(ngx_cycle_t *cycle)
882 {
883 ngx_core_conf_t *ccf;
884
885 /*
886 * ngx_core_module has a special init procedure: it is called by
887 * ngx_init_cycle() before the configuration file parsing to create
888 * ngx_core_module configuration and to set its default parameters
889 */
890
891 if (((void **)(cycle->conf_ctx))[ngx_core_module.index] != NULL) {
892 return NGX_OK;
893 }
894
895 if (!(ccf = ngx_pcalloc(cycle->pool, sizeof(ngx_core_conf_t)))) {
896 return NGX_ERROR;
897 }
898 /* set by pcalloc()
899 *
900 * ccf->pid = NULL;
901 */
902 ccf->daemon = -1;
903 ccf->single = -1;
904
905 ((void **)(cycle->conf_ctx))[ngx_core_module.index] = ccf;
906
907 return NGX_OK;
908 }