comparison src/core/ngx_cycle.c @ 0:f0b350454894 NGINX_0_1_0

nginx 0.1.0 *) The first public version.
author Igor Sysoev <http://sysoev.ru>
date Mon, 04 Oct 2004 00:00:00 +0400
parents
children cc9f381affaa
comparison
equal deleted inserted replaced
-1:000000000000 0:f0b350454894
1
2 /*
3 * Copyright (C) Igor Sysoev
4 */
5
6
7 #include <ngx_config.h>
8 #include <ngx_core.h>
9 #include <ngx_event.h>
10
11
12 static void ngx_clean_old_cycles(ngx_event_t *ev);
13
14
15 volatile ngx_cycle_t *ngx_cycle;
16 ngx_array_t ngx_old_cycles;
17
18 static ngx_pool_t *ngx_temp_pool;
19 static ngx_event_t ngx_cleaner_event;
20
21 ngx_uint_t ngx_test_config;
22
23 #if (NGX_THREADS)
24 ngx_tls_key_t ngx_core_tls_key;
25 #endif
26
27
28 /* STUB NAME */
29 static ngx_connection_t dumb;
30 /* STUB */
31
32 #ifdef NGX_ERROR_LOG_PATH
33 static ngx_str_t error_log = ngx_string(NGX_ERROR_LOG_PATH);
34 #else
35 static ngx_str_t error_log = ngx_null_string;
36 #endif
37
38
39 ngx_cycle_t *ngx_init_cycle(ngx_cycle_t *old_cycle)
40 {
41 void *rv;
42 ngx_uint_t i, n, failed;
43 ngx_log_t *log;
44 ngx_conf_t conf;
45 ngx_pool_t *pool;
46 ngx_cycle_t *cycle, **old;
47 ngx_socket_t fd;
48 ngx_list_part_t *part;
49 ngx_open_file_t *file;
50 ngx_listening_t *ls, *nls;
51 ngx_core_module_t *module;
52
53 log = old_cycle->log;
54
55 if (!(pool = ngx_create_pool(16 * 1024, log))) {
56 return NULL;
57 }
58 pool->log = log;
59
60 if (!(cycle = ngx_pcalloc(pool, sizeof(ngx_cycle_t)))) {
61 ngx_destroy_pool(pool);
62 return NULL;
63 }
64 cycle->pool = pool;
65 cycle->log = log;
66 cycle->old_cycle = old_cycle;
67 cycle->conf_file = old_cycle->conf_file;
68 cycle->root.len = sizeof(NGX_PREFIX) - 1;
69 cycle->root.data = (u_char *) NGX_PREFIX;
70
71
72 n = old_cycle->pathes.nelts ? old_cycle->pathes.nelts : 10;
73 if (!(cycle->pathes.elts = ngx_pcalloc(pool, n * sizeof(ngx_path_t *)))) {
74 ngx_destroy_pool(pool);
75 return NULL;
76 }
77 cycle->pathes.nelts = 0;
78 cycle->pathes.size = sizeof(ngx_path_t *);
79 cycle->pathes.nalloc = n;
80 cycle->pathes.pool = pool;
81
82
83 if (old_cycle->open_files.part.nelts) {
84 n = old_cycle->open_files.part.nelts;
85 for (part = old_cycle->open_files.part.next; part; part = part->next) {
86 n += part->nelts;
87 }
88
89 } else {
90 n = 20;
91 }
92
93 if (ngx_list_init(&cycle->open_files, pool, n, sizeof(ngx_open_file_t))
94 == NGX_ERROR)
95 {
96 ngx_destroy_pool(pool);
97 return NULL;
98 }
99
100
101 if (!(cycle->new_log = ngx_log_create_errlog(cycle, NULL))) {
102 ngx_destroy_pool(pool);
103 return NULL;
104 }
105
106 cycle->new_log->file->name = error_log;
107
108
109 n = old_cycle->listening.nelts ? old_cycle->listening.nelts : 10;
110 cycle->listening.elts = ngx_pcalloc(pool, n * sizeof(ngx_listening_t));
111 if (cycle->listening.elts == NULL) {
112 ngx_destroy_pool(pool);
113 return NULL;
114 }
115 cycle->listening.nelts = 0;
116 cycle->listening.size = sizeof(ngx_listening_t);
117 cycle->listening.nalloc = n;
118 cycle->listening.pool = pool;
119
120
121 cycle->conf_ctx = ngx_pcalloc(pool, ngx_max_module * sizeof(void *));
122 if (cycle->conf_ctx == NULL) {
123 ngx_destroy_pool(pool);
124 return NULL;
125 }
126
127
128 for (i = 0; ngx_modules[i]; i++) {
129 if (ngx_modules[i]->type != NGX_CORE_MODULE) {
130 continue;
131 }
132
133 module = ngx_modules[i]->ctx;
134
135 if (module->create_conf) {
136 rv = module->create_conf(cycle);
137 if (rv == NGX_CONF_ERROR) {
138 ngx_destroy_pool(pool);
139 return NULL;
140 }
141 cycle->conf_ctx[ngx_modules[i]->index] = rv;
142 }
143 }
144
145
146 ngx_memzero(&conf, sizeof(ngx_conf_t));
147 /* STUB: init array ? */
148 conf.args = ngx_create_array(pool, 10, sizeof(ngx_str_t));
149 if (conf.args == NULL) {
150 ngx_destroy_pool(pool);
151 return NULL;
152 }
153
154 conf.ctx = cycle->conf_ctx;
155 conf.cycle = cycle;
156 conf.pool = pool;
157 conf.log = log;
158 conf.module_type = NGX_CORE_MODULE;
159 conf.cmd_type = NGX_MAIN_CONF;
160
161
162 if (ngx_conf_parse(&conf, &cycle->conf_file) != NGX_CONF_OK) {
163 ngx_destroy_pool(pool);
164 return NULL;
165 }
166
167 if (ngx_test_config) {
168 ngx_log_error(NGX_LOG_INFO, log, 0,
169 "the configuration file %s syntax is ok",
170 cycle->conf_file.data);
171 }
172
173
174 for (i = 0; ngx_modules[i]; i++) {
175 if (ngx_modules[i]->type != NGX_CORE_MODULE) {
176 continue;
177 }
178
179 module = ngx_modules[i]->ctx;
180
181 if (module->init_conf) {
182 if (module->init_conf(cycle, cycle->conf_ctx[ngx_modules[i]->index])
183 == NGX_CONF_ERROR)
184 {
185 ngx_destroy_pool(pool);
186 return NULL;
187 }
188 }
189 }
190
191
192 failed = 0;
193
194
195 #if !(WIN32)
196 if (ngx_create_pidfile(cycle, old_cycle) == NGX_ERROR) {
197 failed = 1;
198 }
199 #endif
200
201
202 if (!failed) {
203
204 part = &cycle->open_files.part;
205 file = part->elts;
206
207 for (i = 0; /* void */ ; i++) {
208
209 if (i >= part->nelts) {
210 if (part->next == NULL) {
211 break;
212 }
213 part = part->next;
214 file = part->elts;
215 i = 0;
216 }
217
218 if (file[i].name.data == NULL) {
219 continue;
220 }
221
222 file[i].fd = ngx_open_file(file[i].name.data,
223 NGX_FILE_RDWR,
224 NGX_FILE_CREATE_OR_OPEN|NGX_FILE_APPEND);
225
226 #if 0
227 log->log_level = NGX_LOG_DEBUG_ALL;
228 #endif
229 ngx_log_debug3(NGX_LOG_DEBUG_CORE, log, 0,
230 "log: %0X %d \"%s\"",
231 &file[i], file[i].fd, file[i].name.data);
232
233 if (file[i].fd == NGX_INVALID_FILE) {
234 ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
235 ngx_open_file_n " \"%s\" failed",
236 file[i].name.data);
237 failed = 1;
238 break;
239 }
240
241 #if (WIN32)
242 if (ngx_file_append_mode(file[i].fd) == NGX_ERROR) {
243 ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
244 ngx_file_append_mode_n " \"%s\" failed",
245 file[i].name.data);
246 failed = 1;
247 break;
248 }
249 #else
250 if (fcntl(file[i].fd, F_SETFD, FD_CLOEXEC) == -1) {
251 ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
252 "fcntl(FD_CLOEXEC) \"%s\" failed",
253 file[i].name.data);
254 failed = 1;
255 break;
256 }
257 #endif
258 }
259 }
260
261 cycle->log = cycle->new_log;
262 pool->log = cycle->new_log;
263
264 if (cycle->log->log_level == 0) {
265 cycle->log->log_level = NGX_LOG_ERR;
266 }
267
268 if (!failed) {
269 if (old_cycle->listening.nelts) {
270 ls = old_cycle->listening.elts;
271 for (i = 0; i < old_cycle->listening.nelts; i++) {
272 ls[i].remain = 0;
273 }
274
275 nls = cycle->listening.elts;
276 for (n = 0; n < cycle->listening.nelts; n++) {
277 for (i = 0; i < old_cycle->listening.nelts; i++) {
278 if (ls[i].ignore) {
279 continue;
280 }
281
282 if (ngx_memcmp(nls[n].sockaddr,
283 ls[i].sockaddr, ls[i].socklen) == 0)
284 {
285 fd = ls[i].fd;
286 #if (WIN32)
287 /*
288 * Winsock assignes a socket number divisible by 4 so
289 * to find a connection we divide a socket number by 4.
290 */
291
292 fd /= 4;
293 #endif
294 if (fd >= (ngx_socket_t) cycle->connection_n) {
295 ngx_log_error(NGX_LOG_EMERG, log, 0,
296 "%d connections is not enough to hold "
297 "an open listening socket on %s, "
298 "required at least %d connections",
299 cycle->connection_n,
300 ls[i].addr_text.data, fd);
301 failed = 1;
302 break;
303 }
304
305 nls[n].fd = ls[i].fd;
306 nls[i].remain = 1;
307 ls[i].remain = 1;
308 break;
309 }
310 }
311
312 if (nls[n].fd == -1) {
313 nls[n].new = 1;
314 }
315 }
316
317 } else {
318 ls = cycle->listening.elts;
319 for (i = 0; i < cycle->listening.nelts; i++) {
320 ls[i].new = 1;
321 }
322 }
323
324 if (!ngx_test_config && !failed) {
325 if (ngx_open_listening_sockets(cycle) == NGX_ERROR) {
326 failed = 1;
327 }
328 }
329 }
330
331 if (failed) {
332
333 /* rollback the new cycle configuration */
334
335 part = &cycle->open_files.part;
336 file = part->elts;
337
338 for (i = 0; /* void */ ; i++) {
339
340 if (i >= part->nelts) {
341 if (part->next == NULL) {
342 break;
343 }
344 part = part->next;
345 file = part->elts;
346 i = 0;
347 }
348
349 if (file[i].fd == NGX_INVALID_FILE
350 || file[i].fd == ngx_stderr_fileno)
351 {
352 continue;
353 }
354
355 if (ngx_close_file(file[i].fd) == NGX_FILE_ERROR) {
356 ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
357 ngx_close_file_n " \"%s\" failed",
358 file[i].name.data);
359 }
360 }
361
362 if (ngx_test_config) {
363 ngx_destroy_pool(pool);
364 return NULL;
365 }
366
367 ls = cycle->listening.elts;
368 for (i = 0; i < cycle->listening.nelts; i++) {
369 if (ls[i].fd == -1 || !ls[i].new) {
370 continue;
371 }
372
373 if (ngx_close_socket(ls[i].fd) == -1) {
374 ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
375 ngx_close_socket_n " %s failed",
376 ls[i].addr_text.data);
377 }
378 }
379
380 ngx_destroy_pool(pool);
381 return NULL;
382 }
383
384
385 /* commit the new cycle configuration */
386
387 #if !(WIN32)
388
389 if (!ngx_test_config && cycle->log->file->fd != STDERR_FILENO) {
390
391 ngx_log_debug3(NGX_LOG_DEBUG_CORE, log, 0,
392 "dup2: %0X %d \"%s\"",
393 cycle->log->file,
394 cycle->log->file->fd, cycle->log->file->name.data);
395
396 if (dup2(cycle->log->file->fd, STDERR_FILENO) == NGX_ERROR) {
397 ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
398 "dup2(STDERR) failed");
399 /* fatal */
400 exit(1);
401 }
402 }
403
404 #endif
405
406 pool->log = cycle->log;
407
408 for (i = 0; ngx_modules[i]; i++) {
409 if (ngx_modules[i]->init_module) {
410 if (ngx_modules[i]->init_module(cycle) == NGX_ERROR) {
411 /* fatal */
412 exit(1);
413 }
414 }
415 }
416
417 /* close and delete stuff that lefts from an old cycle */
418
419 /* close the unneeded listening sockets */
420
421 ls = old_cycle->listening.elts;
422 for (i = 0; i < old_cycle->listening.nelts; i++) {
423 if (ls[i].remain) {
424 continue;
425 }
426
427 if (ngx_close_socket(ls[i].fd) == -1) {
428 ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
429 ngx_close_socket_n " %s failed",
430 ls[i].addr_text.data);
431 }
432 }
433
434
435 /* close the unneeded open files */
436
437 part = &old_cycle->open_files.part;
438 file = part->elts;
439
440 for (i = 0; /* void */ ; i++) {
441
442 if (i >= part->nelts) {
443 if (part->next == NULL) {
444 break;
445 }
446 part = part->next;
447 file = part->elts;
448 i = 0;
449 }
450
451 if (file[i].fd == NGX_INVALID_FILE || file[i].fd == ngx_stderr_fileno) {
452 continue;
453 }
454
455 if (ngx_close_file(file[i].fd) == NGX_FILE_ERROR) {
456 ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
457 ngx_close_file_n " \"%s\" failed",
458 file[i].name.data);
459 }
460 }
461
462 if (old_cycle->connections == NULL) {
463 /* an old cycle is an init cycle */
464 ngx_destroy_pool(old_cycle->pool);
465 return cycle;
466 }
467
468 if (ngx_process == NGX_PROCESS_MASTER) {
469 ngx_destroy_pool(old_cycle->pool);
470 return cycle;
471 }
472
473 if (ngx_temp_pool == NULL) {
474 ngx_temp_pool = ngx_create_pool(128, cycle->log);
475 if (ngx_temp_pool == NULL) {
476 ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
477 "can not create ngx_temp_pool");
478 exit(1);
479 }
480
481 n = 10;
482 ngx_old_cycles.elts = ngx_pcalloc(ngx_temp_pool,
483 n * sizeof(ngx_cycle_t *));
484 if (ngx_old_cycles.elts == NULL) {
485 exit(1);
486 }
487 ngx_old_cycles.nelts = 0;
488 ngx_old_cycles.size = sizeof(ngx_cycle_t *);
489 ngx_old_cycles.nalloc = n;
490 ngx_old_cycles.pool = ngx_temp_pool;
491
492 ngx_cleaner_event.event_handler = ngx_clean_old_cycles;
493 ngx_cleaner_event.log = cycle->log;
494 ngx_cleaner_event.data = &dumb;
495 dumb.fd = (ngx_socket_t) -1;
496 }
497
498 ngx_temp_pool->log = cycle->log;
499
500 old = ngx_push_array(&ngx_old_cycles);
501 if (old == NULL) {
502 exit(1);
503 }
504 *old = old_cycle;
505
506 if (!ngx_cleaner_event.timer_set) {
507 ngx_add_timer(&ngx_cleaner_event, 30000);
508 ngx_cleaner_event.timer_set = 1;
509 }
510
511 return cycle;
512 }
513
514
515 #if !(WIN32)
516
517 ngx_int_t ngx_create_pidfile(ngx_cycle_t *cycle, ngx_cycle_t *old_cycle)
518 {
519 ngx_uint_t trunc;
520 size_t len;
521 u_char *name, pid[NGX_INT64_LEN + 1];
522 ngx_file_t file;
523 ngx_core_conf_t *ccf, *old_ccf;
524
525 if (!ngx_test_config && old_cycle && old_cycle->conf_ctx == NULL) {
526
527 /*
528 * do not create the pid file in the first ngx_init_cycle() call
529 * because we need to write the demonized process pid
530 */
531
532 return NGX_OK;
533 }
534
535 ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
536
537 if (!ngx_test_config && old_cycle) {
538 old_ccf = (ngx_core_conf_t *) ngx_get_conf(old_cycle->conf_ctx,
539 ngx_core_module);
540
541 if (ccf->pid.len == old_ccf->pid.len
542 && ngx_strcmp(ccf->pid.data, old_ccf->pid.data) == 0)
543 {
544
545 /* pid file name is the same */
546
547 return NGX_OK;
548 }
549 }
550
551 len = ngx_snprintf((char *) pid, NGX_INT64_LEN + 1, PID_T_FMT, ngx_pid);
552
553 ngx_memzero(&file, sizeof(ngx_file_t));
554 file.name = (ngx_inherited && getppid() > 1) ? ccf->newpid : ccf->pid;
555 file.log = cycle->log;
556
557 trunc = ngx_test_config ? 0: NGX_FILE_TRUNCATE;
558
559 file.fd = ngx_open_file(file.name.data, NGX_FILE_RDWR,
560 NGX_FILE_CREATE_OR_OPEN|trunc);
561
562 if (file.fd == NGX_INVALID_FILE) {
563 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
564 ngx_open_file_n " \"%s\" failed", file.name.data);
565 return NGX_ERROR;
566 }
567
568 if (!ngx_test_config) {
569 if (ngx_write_file(&file, pid, len, 0) == NGX_ERROR) {
570 return NGX_ERROR;
571 }
572 }
573
574 if (ngx_close_file(file.fd) == NGX_FILE_ERROR) {
575 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
576 ngx_close_file_n " \"%s\" failed", file.name.data);
577 }
578
579 ngx_delete_pidfile(old_cycle);
580
581 return NGX_OK;
582 }
583
584
585 void ngx_delete_pidfile(ngx_cycle_t *cycle)
586 {
587 u_char *name;
588 ngx_core_conf_t *ccf;
589
590 if (cycle == NULL || cycle->conf_ctx == NULL) {
591 return;
592 }
593
594 ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
595
596 if (ngx_inherited && getppid() > 1) {
597 name = ccf->newpid.data;
598
599 } else {
600 name = ccf->pid.data;
601 }
602
603 if (ngx_delete_file(name) == NGX_FILE_ERROR) {
604 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
605 ngx_delete_file_n " \"%s\" failed", name);
606 }
607 }
608
609 #endif
610
611
612 void ngx_reopen_files(ngx_cycle_t *cycle, ngx_uid_t user)
613 {
614 ngx_fd_t fd;
615 ngx_uint_t i;
616 ngx_list_part_t *part;
617 ngx_open_file_t *file;
618
619 part = &cycle->open_files.part;
620 file = part->elts;
621
622 for (i = 0; /* void */ ; i++) {
623
624 if (i >= part->nelts) {
625 if (part->next == NULL) {
626 break;
627 }
628 part = part->next;
629 i = 0;
630 }
631
632 if (file[i].name.data == NULL) {
633 continue;
634 }
635
636 fd = ngx_open_file(file[i].name.data, NGX_FILE_RDWR,
637 NGX_FILE_CREATE_OR_OPEN|NGX_FILE_APPEND);
638
639 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
640 "reopen file \"%s\", old:%d new:%d",
641 file[i].name.data, file[i].fd, fd);
642
643 if (fd == NGX_INVALID_FILE) {
644 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
645 ngx_open_file_n " \"%s\" failed", file[i].name.data);
646 continue;
647 }
648
649 #if (WIN32)
650 if (ngx_file_append_mode(fd) == NGX_ERROR) {
651 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
652 ngx_file_append_mode_n " \"%s\" failed",
653 file[i].name.data);
654
655 if (ngx_close_file(fd) == NGX_FILE_ERROR) {
656 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
657 ngx_close_file_n " \"%s\" failed",
658 file[i].name.data);
659 }
660
661 continue;
662 }
663 #else
664 if (user != (ngx_uid_t) -1) {
665 if (chown((const char *) file[i].name.data, user, -1) == -1) {
666 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
667 "chown \"%s\" failed", file[i].name.data);
668
669 if (ngx_close_file(fd) == NGX_FILE_ERROR) {
670 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
671 ngx_close_file_n " \"%s\" failed",
672 file[i].name.data);
673 }
674 }
675 }
676
677 if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) {
678 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
679 "fcntl(FD_CLOEXEC) \"%s\" failed",
680 file[i].name.data);
681
682 if (ngx_close_file(fd) == NGX_FILE_ERROR) {
683 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
684 ngx_close_file_n " \"%s\" failed",
685 file[i].name.data);
686 }
687
688 continue;
689 }
690 #endif
691
692 if (ngx_close_file(file[i].fd) == NGX_FILE_ERROR) {
693 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
694 ngx_close_file_n " \"%s\" failed",
695 file[i].name.data);
696 }
697
698 file[i].fd = fd;
699 }
700
701 #if !(WIN32)
702
703 if (cycle->log->file->fd != STDERR_FILENO) {
704 if (dup2(cycle->log->file->fd, STDERR_FILENO) == -1) {
705 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
706 "dup2(STDERR) failed");
707 }
708 }
709
710 #endif
711 }
712
713
714 static void ngx_clean_old_cycles(ngx_event_t *ev)
715 {
716 ngx_uint_t i, n, found, live;
717 ngx_log_t *log;
718 ngx_cycle_t **cycle;
719
720 log = ngx_cycle->log;
721 ngx_temp_pool->log = log;
722
723 ngx_log_debug0(NGX_LOG_DEBUG_CORE, log, 0, "clean old cycles");
724
725 live = 0;
726
727 cycle = ngx_old_cycles.elts;
728 for (i = 0; i < ngx_old_cycles.nelts; i++) {
729
730 if (cycle[i] == NULL) {
731 continue;
732 }
733
734 found = 0;
735
736 for (n = 0; n < cycle[i]->connection_n; n++) {
737 if (cycle[i]->connections[n].fd != (ngx_socket_t) -1) {
738 found = 1;
739
740 ngx_log_debug1(NGX_LOG_DEBUG_CORE, log, 0, "live fd:%d", n);
741
742 break;
743 }
744 }
745
746 if (found) {
747 live = 1;
748 continue;
749 }
750
751 ngx_log_debug1(NGX_LOG_DEBUG_CORE, log, 0, "clean old cycle: %d", i);
752
753 ngx_destroy_pool(cycle[i]->pool);
754 cycle[i] = NULL;
755 }
756
757 ngx_log_debug1(NGX_LOG_DEBUG_CORE, log, 0, "old cycles status: %d", live);
758
759 if (live) {
760 ngx_add_timer(ev, 30000);
761
762 } else {
763 ngx_destroy_pool(ngx_temp_pool);
764 ngx_temp_pool = NULL;
765 ngx_old_cycles.nelts = 0;
766 }
767 }