nginx 0.1.1
[nginx-catap.git] / src / core / ngx_cycle.c
blob38f4ad505a06c5e9237bc604507bb44cdb2d3939
2 /*
3 * Copyright (C) Igor Sysoev
4 */
7 #include <ngx_config.h>
8 #include <ngx_core.h>
9 #include <ngx_event.h>
12 static void ngx_clean_old_cycles(ngx_event_t *ev);
15 volatile ngx_cycle_t *ngx_cycle;
16 ngx_array_t ngx_old_cycles;
18 static ngx_pool_t *ngx_temp_pool;
19 static ngx_event_t ngx_cleaner_event;
21 ngx_uint_t ngx_test_config;
23 #if (NGX_THREADS)
24 ngx_tls_key_t ngx_core_tls_key;
25 #endif
28 /* STUB NAME */
29 static ngx_connection_t dumb;
30 /* STUB */
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
39 ngx_cycle_t *ngx_init_cycle(ngx_cycle_t *old_cycle)
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;
53 log = old_cycle->log;
55 if (!(pool = ngx_create_pool(16 * 1024, log))) {
56 return NULL;
58 pool->log = log;
60 if (!(cycle = ngx_pcalloc(pool, sizeof(ngx_cycle_t)))) {
61 ngx_destroy_pool(pool);
62 return NULL;
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;
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;
77 cycle->pathes.nelts = 0;
78 cycle->pathes.size = sizeof(ngx_path_t *);
79 cycle->pathes.nalloc = n;
80 cycle->pathes.pool = pool;
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;
89 } else {
90 n = 20;
93 if (ngx_list_init(&cycle->open_files, pool, n, sizeof(ngx_open_file_t))
94 == NGX_ERROR)
96 ngx_destroy_pool(pool);
97 return NULL;
101 if (!(cycle->new_log = ngx_log_create_errlog(cycle, NULL))) {
102 ngx_destroy_pool(pool);
103 return NULL;
106 cycle->new_log->file->name = error_log;
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;
115 cycle->listening.nelts = 0;
116 cycle->listening.size = sizeof(ngx_listening_t);
117 cycle->listening.nalloc = n;
118 cycle->listening.pool = pool;
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;
128 for (i = 0; ngx_modules[i]; i++) {
129 if (ngx_modules[i]->type != NGX_CORE_MODULE) {
130 continue;
133 module = ngx_modules[i]->ctx;
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;
141 cycle->conf_ctx[ngx_modules[i]->index] = rv;
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;
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;
162 if (ngx_conf_parse(&conf, &cycle->conf_file) != NGX_CONF_OK) {
163 ngx_destroy_pool(pool);
164 return NULL;
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);
174 for (i = 0; ngx_modules[i]; i++) {
175 if (ngx_modules[i]->type != NGX_CORE_MODULE) {
176 continue;
179 module = ngx_modules[i]->ctx;
181 if (module->init_conf) {
182 if (module->init_conf(cycle, cycle->conf_ctx[ngx_modules[i]->index])
183 == NGX_CONF_ERROR)
185 ngx_destroy_pool(pool);
186 return NULL;
192 failed = 0;
195 #if !(WIN32)
196 if (ngx_create_pidfile(cycle, old_cycle) == NGX_ERROR) {
197 failed = 1;
199 #endif
202 if (!failed) {
204 part = &cycle->open_files.part;
205 file = part->elts;
207 for (i = 0; /* void */ ; i++) {
209 if (i >= part->nelts) {
210 if (part->next == NULL) {
211 break;
213 part = part->next;
214 file = part->elts;
215 i = 0;
218 if (file[i].name.data == NULL) {
219 continue;
222 file[i].fd = ngx_open_file(file[i].name.data,
223 NGX_FILE_RDWR,
224 NGX_FILE_CREATE_OR_OPEN|NGX_FILE_APPEND);
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);
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;
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;
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;
257 #endif
261 cycle->log = cycle->new_log;
262 pool->log = cycle->new_log;
264 if (cycle->log->log_level == 0) {
265 cycle->log->log_level = NGX_LOG_ERR;
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;
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;
282 if (ngx_memcmp(nls[n].sockaddr,
283 ls[i].sockaddr, ls[i].socklen) == 0)
285 fd = ls[i].fd;
286 #if (WIN32)
288 * Winsock assignes a socket number divisible by 4 so
289 * to find a connection we divide a socket number by 4.
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;
305 nls[n].fd = ls[i].fd;
306 nls[i].remain = 1;
307 ls[i].remain = 1;
308 break;
312 if (nls[n].fd == -1) {
313 nls[n].new = 1;
317 } else {
318 ls = cycle->listening.elts;
319 for (i = 0; i < cycle->listening.nelts; i++) {
320 ls[i].new = 1;
324 if (!ngx_test_config && !failed) {
325 if (ngx_open_listening_sockets(cycle) == NGX_ERROR) {
326 failed = 1;
331 if (failed) {
333 /* rollback the new cycle configuration */
335 part = &cycle->open_files.part;
336 file = part->elts;
338 for (i = 0; /* void */ ; i++) {
340 if (i >= part->nelts) {
341 if (part->next == NULL) {
342 break;
344 part = part->next;
345 file = part->elts;
346 i = 0;
349 if (file[i].fd == NGX_INVALID_FILE
350 || file[i].fd == ngx_stderr_fileno)
352 continue;
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);
362 if (ngx_test_config) {
363 ngx_destroy_pool(pool);
364 return NULL;
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;
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);
380 ngx_destroy_pool(pool);
381 return NULL;
385 /* commit the new cycle configuration */
387 #if !(WIN32)
389 if (!ngx_test_config && cycle->log->file->fd != STDERR_FILENO) {
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);
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);
404 #endif
406 pool->log = cycle->log;
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);
417 /* close and delete stuff that lefts from an old cycle */
419 /* close the unneeded listening sockets */
421 ls = old_cycle->listening.elts;
422 for (i = 0; i < old_cycle->listening.nelts; i++) {
423 if (ls[i].remain) {
424 continue;
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);
435 /* close the unneeded open files */
437 part = &old_cycle->open_files.part;
438 file = part->elts;
440 for (i = 0; /* void */ ; i++) {
442 if (i >= part->nelts) {
443 if (part->next == NULL) {
444 break;
446 part = part->next;
447 file = part->elts;
448 i = 0;
451 if (file[i].fd == NGX_INVALID_FILE || file[i].fd == ngx_stderr_fileno) {
452 continue;
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);
462 if (old_cycle->connections == NULL) {
463 /* an old cycle is an init cycle */
464 ngx_destroy_pool(old_cycle->pool);
465 return cycle;
468 if (ngx_process == NGX_PROCESS_MASTER) {
469 ngx_destroy_pool(old_cycle->pool);
470 return cycle;
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);
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);
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;
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;
498 ngx_temp_pool->log = cycle->log;
500 old = ngx_push_array(&ngx_old_cycles);
501 if (old == NULL) {
502 exit(1);
504 *old = old_cycle;
506 if (!ngx_cleaner_event.timer_set) {
507 ngx_add_timer(&ngx_cleaner_event, 30000);
508 ngx_cleaner_event.timer_set = 1;
511 return cycle;
515 #if !(WIN32)
517 ngx_int_t ngx_create_pidfile(ngx_cycle_t *cycle, ngx_cycle_t *old_cycle)
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;
525 if (!ngx_test_config && old_cycle && old_cycle->conf_ctx == NULL) {
528 * do not create the pid file in the first ngx_init_cycle() call
529 * because we need to write the demonized process pid
532 return NGX_OK;
535 ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
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);
541 if (ccf->pid.len == old_ccf->pid.len
542 && ngx_strcmp(ccf->pid.data, old_ccf->pid.data) == 0)
545 /* pid file name is the same */
547 return NGX_OK;
551 len = ngx_snprintf((char *) pid, NGX_INT64_LEN + 1, PID_T_FMT, ngx_pid);
553 ngx_memzero(&file, sizeof(ngx_file_t));
554 file.name = (ngx_inherited && getppid() > 1) ? ccf->newpid : ccf->pid;
555 file.log = cycle->log;
557 trunc = ngx_test_config ? 0: NGX_FILE_TRUNCATE;
559 file.fd = ngx_open_file(file.name.data, NGX_FILE_RDWR,
560 NGX_FILE_CREATE_OR_OPEN|trunc);
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;
568 if (!ngx_test_config) {
569 if (ngx_write_file(&file, pid, len, 0) == NGX_ERROR) {
570 return NGX_ERROR;
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);
579 ngx_delete_pidfile(old_cycle);
581 return NGX_OK;
585 void ngx_delete_pidfile(ngx_cycle_t *cycle)
587 u_char *name;
588 ngx_core_conf_t *ccf;
590 if (cycle == NULL || cycle->conf_ctx == NULL) {
591 return;
594 ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
596 if (ngx_inherited && getppid() > 1) {
597 name = ccf->newpid.data;
599 } else {
600 name = ccf->pid.data;
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);
609 #endif
612 void ngx_reopen_files(ngx_cycle_t *cycle, ngx_uid_t user)
614 ngx_fd_t fd;
615 ngx_uint_t i;
616 ngx_list_part_t *part;
617 ngx_open_file_t *file;
618 #if !(WIN32)
619 ngx_file_info_t fi;
620 #endif
622 part = &cycle->open_files.part;
623 file = part->elts;
625 for (i = 0; /* void */ ; i++) {
627 if (i >= part->nelts) {
628 if (part->next == NULL) {
629 break;
631 part = part->next;
632 i = 0;
635 if (file[i].name.data == NULL) {
636 continue;
639 fd = ngx_open_file(file[i].name.data, NGX_FILE_RDWR,
640 NGX_FILE_CREATE_OR_OPEN|NGX_FILE_APPEND);
642 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
643 "reopen file \"%s\", old:%d new:%d",
644 file[i].name.data, file[i].fd, fd);
646 if (fd == NGX_INVALID_FILE) {
647 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
648 ngx_open_file_n " \"%s\" failed", file[i].name.data);
649 continue;
652 #if (WIN32)
653 if (ngx_file_append_mode(fd) == NGX_ERROR) {
654 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
655 ngx_file_append_mode_n " \"%s\" failed",
656 file[i].name.data);
658 if (ngx_close_file(fd) == NGX_FILE_ERROR) {
659 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
660 ngx_close_file_n " \"%s\" failed",
661 file[i].name.data);
664 continue;
666 #else
667 if (user != (ngx_uid_t) -1) {
668 if (chown((const char *) file[i].name.data, user, -1) == -1) {
669 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
670 "chown \"%s\" failed", file[i].name.data);
672 if (ngx_close_file(fd) == NGX_FILE_ERROR) {
673 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
674 ngx_close_file_n " \"%s\" failed",
675 file[i].name.data);
679 if (ngx_file_info((const char *) file[i].name.data, &fi) == -1) {
680 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
681 ngx_file_info_n " \"%s\" failed",
682 file[i].name.data);
684 if (ngx_close_file(fd) == NGX_FILE_ERROR) {
685 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
686 ngx_close_file_n " \"%s\" failed",
687 file[i].name.data);
691 if ((fi.st_mode & (S_IRUSR|S_IWUSR)) != (S_IRUSR|S_IWUSR)) {
693 fi.st_mode |= (S_IRUSR|S_IWUSR);
695 if (chmod((const char *) file[i].name.data, fi.st_mode) == -1) {
696 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
697 "chmod \"%s\" failed",
698 file[i].name.data);
700 if (ngx_close_file(fd) == NGX_FILE_ERROR) {
701 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
702 ngx_close_file_n " \"%s\" failed",
703 file[i].name.data);
709 if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) {
710 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
711 "fcntl(FD_CLOEXEC) \"%s\" failed",
712 file[i].name.data);
714 if (ngx_close_file(fd) == NGX_FILE_ERROR) {
715 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
716 ngx_close_file_n " \"%s\" failed",
717 file[i].name.data);
720 continue;
722 #endif
724 if (ngx_close_file(file[i].fd) == NGX_FILE_ERROR) {
725 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
726 ngx_close_file_n " \"%s\" failed",
727 file[i].name.data);
730 file[i].fd = fd;
733 #if !(WIN32)
735 if (cycle->log->file->fd != STDERR_FILENO) {
736 if (dup2(cycle->log->file->fd, STDERR_FILENO) == -1) {
737 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
738 "dup2(STDERR) failed");
742 #endif
746 static void ngx_clean_old_cycles(ngx_event_t *ev)
748 ngx_uint_t i, n, found, live;
749 ngx_log_t *log;
750 ngx_cycle_t **cycle;
752 log = ngx_cycle->log;
753 ngx_temp_pool->log = log;
755 ngx_log_debug0(NGX_LOG_DEBUG_CORE, log, 0, "clean old cycles");
757 live = 0;
759 cycle = ngx_old_cycles.elts;
760 for (i = 0; i < ngx_old_cycles.nelts; i++) {
762 if (cycle[i] == NULL) {
763 continue;
766 found = 0;
768 for (n = 0; n < cycle[i]->connection_n; n++) {
769 if (cycle[i]->connections[n].fd != (ngx_socket_t) -1) {
770 found = 1;
772 ngx_log_debug1(NGX_LOG_DEBUG_CORE, log, 0, "live fd:%d", n);
774 break;
778 if (found) {
779 live = 1;
780 continue;
783 ngx_log_debug1(NGX_LOG_DEBUG_CORE, log, 0, "clean old cycle: %d", i);
785 ngx_destroy_pool(cycle[i]->pool);
786 cycle[i] = NULL;
789 ngx_log_debug1(NGX_LOG_DEBUG_CORE, log, 0, "old cycles status: %d", live);
791 if (live) {
792 ngx_add_timer(ev, 30000);
794 } else {
795 ngx_destroy_pool(ngx_temp_pool);
796 ngx_temp_pool = NULL;
797 ngx_old_cycles.nelts = 0;