3 * Copyright (C) Igor Sysoev
7 #include <ngx_config.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
;
24 ngx_tls_key_t ngx_core_tls_key
;
29 static ngx_connection_t dumb
;
32 #ifdef NGX_ERROR_LOG_PATH
33 static ngx_str_t error_log
= ngx_string(NGX_ERROR_LOG_PATH
);
35 static ngx_str_t error_log
= ngx_null_string
;
39 ngx_cycle_t
*ngx_init_cycle(ngx_cycle_t
*old_cycle
)
42 ngx_uint_t i
, n
, failed
;
46 ngx_cycle_t
*cycle
, **old
;
48 ngx_list_part_t
*part
;
49 ngx_open_file_t
*file
;
50 ngx_listening_t
*ls
, *nls
;
51 ngx_core_module_t
*module
;
55 if (!(pool
= ngx_create_pool(16 * 1024, log
))) {
60 if (!(cycle
= ngx_pcalloc(pool
, sizeof(ngx_cycle_t
)))) {
61 ngx_destroy_pool(pool
);
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
);
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
) {
93 if (ngx_list_init(&cycle
->open_files
, pool
, n
, sizeof(ngx_open_file_t
))
96 ngx_destroy_pool(pool
);
101 if (!(cycle
->new_log
= ngx_log_create_errlog(cycle
, NULL
))) {
102 ngx_destroy_pool(pool
);
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
);
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
);
128 for (i
= 0; ngx_modules
[i
]; i
++) {
129 if (ngx_modules
[i
]->type
!= NGX_CORE_MODULE
) {
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
);
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
);
154 conf
.ctx
= cycle
->conf_ctx
;
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
);
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
) {
179 module
= ngx_modules
[i
]->ctx
;
181 if (module
->init_conf
) {
182 if (module
->init_conf(cycle
, cycle
->conf_ctx
[ngx_modules
[i
]->index
])
185 ngx_destroy_pool(pool
);
196 if (ngx_create_pidfile(cycle
, old_cycle
) == NGX_ERROR
) {
204 part
= &cycle
->open_files
.part
;
207 for (i
= 0; /* void */ ; i
++) {
209 if (i
>= part
->nelts
) {
210 if (part
->next
== NULL
) {
218 if (file
[i
].name
.data
== NULL
) {
222 file
[i
].fd
= ngx_open_file(file
[i
].name
.data
,
224 NGX_FILE_CREATE_OR_OPEN
|NGX_FILE_APPEND
);
227 log
->log_level
= NGX_LOG_DEBUG_ALL
;
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",
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",
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",
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
;
269 if (old_cycle
->listening
.nelts
) {
270 ls
= old_cycle
->listening
.elts
;
271 for (i
= 0; i
< old_cycle
->listening
.nelts
; i
++) {
275 nls
= cycle
->listening
.elts
;
276 for (n
= 0; n
< cycle
->listening
.nelts
; n
++) {
277 for (i
= 0; i
< old_cycle
->listening
.nelts
; i
++) {
282 if (ngx_memcmp(nls
[n
].sockaddr
,
283 ls
[i
].sockaddr
, ls
[i
].socklen
) == 0)
288 * Winsock assignes a socket number divisible by 4 so
289 * to find a connection we divide a socket number by 4.
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",
300 ls
[i
].addr_text
.data
, fd
);
305 nls
[n
].fd
= ls
[i
].fd
;
312 if (nls
[n
].fd
== -1) {
318 ls
= cycle
->listening
.elts
;
319 for (i
= 0; i
< cycle
->listening
.nelts
; i
++) {
324 if (!ngx_test_config
&& !failed
) {
325 if (ngx_open_listening_sockets(cycle
) == NGX_ERROR
) {
333 /* rollback the new cycle configuration */
335 part
= &cycle
->open_files
.part
;
338 for (i
= 0; /* void */ ; i
++) {
340 if (i
>= part
->nelts
) {
341 if (part
->next
== NULL
) {
349 if (file
[i
].fd
== NGX_INVALID_FILE
350 || file
[i
].fd
== ngx_stderr_fileno
)
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",
362 if (ngx_test_config
) {
363 ngx_destroy_pool(pool
);
367 ls
= cycle
->listening
.elts
;
368 for (i
= 0; i
< cycle
->listening
.nelts
; i
++) {
369 if (ls
[i
].fd
== -1 || !ls
[i
].new) {
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
);
385 /* commit the new cycle configuration */
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\"",
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");
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
) {
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
++) {
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
;
440 for (i
= 0; /* void */ ; i
++) {
442 if (i
>= part
->nelts
) {
443 if (part
->next
== NULL
) {
451 if (file
[i
].fd
== NGX_INVALID_FILE
|| file
[i
].fd
== ngx_stderr_fileno
) {
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",
462 if (old_cycle
->connections
== NULL
) {
463 /* an old cycle is an init cycle */
464 ngx_destroy_pool(old_cycle
->pool
);
468 if (ngx_process
== NGX_PROCESS_MASTER
) {
469 ngx_destroy_pool(old_cycle
->pool
);
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");
482 ngx_old_cycles
.elts
= ngx_pcalloc(ngx_temp_pool
,
483 n
* sizeof(ngx_cycle_t
*));
484 if (ngx_old_cycles
.elts
== NULL
) {
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
);
506 if (!ngx_cleaner_event
.timer_set
) {
507 ngx_add_timer(&ngx_cleaner_event
, 30000);
508 ngx_cleaner_event
.timer_set
= 1;
517 ngx_int_t
ngx_create_pidfile(ngx_cycle_t
*cycle
, ngx_cycle_t
*old_cycle
)
521 u_char
*name
, pid
[NGX_INT64_LEN
+ 1];
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
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
,
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 */
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
);
568 if (!ngx_test_config
) {
569 if (ngx_write_file(&file
, pid
, len
, 0) == 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
);
585 void ngx_delete_pidfile(ngx_cycle_t
*cycle
)
588 ngx_core_conf_t
*ccf
;
590 if (cycle
== NULL
|| cycle
->conf_ctx
== NULL
) {
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
;
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
);
612 void ngx_reopen_files(ngx_cycle_t
*cycle
, ngx_uid_t user
)
616 ngx_list_part_t
*part
;
617 ngx_open_file_t
*file
;
622 part
= &cycle
->open_files
.part
;
625 for (i
= 0; /* void */ ; i
++) {
627 if (i
>= part
->nelts
) {
628 if (part
->next
== NULL
) {
635 if (file
[i
].name
.data
== NULL
) {
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
);
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",
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",
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",
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",
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",
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",
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",
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",
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",
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",
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");
746 static void ngx_clean_old_cycles(ngx_event_t
*ev
)
748 ngx_uint_t i
, n
, found
, live
;
752 log
= ngx_cycle
->log
;
753 ngx_temp_pool
->log
= log
;
755 ngx_log_debug0(NGX_LOG_DEBUG_CORE
, log
, 0, "clean old cycles");
759 cycle
= ngx_old_cycles
.elts
;
760 for (i
= 0; i
< ngx_old_cycles
.nelts
; i
++) {
762 if (cycle
[i
] == NULL
) {
768 for (n
= 0; n
< cycle
[i
]->connection_n
; n
++) {
769 if (cycle
[i
]->connections
[n
].fd
!= (ngx_socket_t
) -1) {
772 ngx_log_debug1(NGX_LOG_DEBUG_CORE
, log
, 0, "live fd:%d", n
);
783 ngx_log_debug1(NGX_LOG_DEBUG_CORE
, log
, 0, "clean old cycle: %d", i
);
785 ngx_destroy_pool(cycle
[i
]->pool
);
789 ngx_log_debug1(NGX_LOG_DEBUG_CORE
, log
, 0, "old cycles status: %d", live
);
792 ngx_add_timer(ev
, 30000);
795 ngx_destroy_pool(ngx_temp_pool
);
796 ngx_temp_pool
= NULL
;
797 ngx_old_cycles
.nelts
= 0;