3 * Copyright (C) Igor Sysoev
7 #include <ngx_config.h>
12 static ngx_int_t
ngx_cmp_sockaddr(struct sockaddr
*sa1
, struct sockaddr
*sa2
);
13 static void ngx_clean_old_cycles(ngx_event_t
*ev
);
16 volatile ngx_cycle_t
*ngx_cycle
;
17 ngx_array_t ngx_old_cycles
;
19 static ngx_pool_t
*ngx_temp_pool
;
20 static ngx_event_t ngx_cleaner_event
;
22 ngx_uint_t ngx_test_config
;
25 ngx_tls_key_t ngx_core_tls_key
;
30 static ngx_connection_t dumb
;
33 #ifdef NGX_ERROR_LOG_PATH
34 static ngx_str_t error_log
= ngx_string(NGX_ERROR_LOG_PATH
);
36 static ngx_str_t error_log
= ngx_null_string
;
40 ngx_cycle_t
*ngx_init_cycle(ngx_cycle_t
*old_cycle
)
43 ngx_uint_t i
, n
, failed
;
47 ngx_cycle_t
*cycle
, **old
;
49 ngx_list_part_t
*part
;
50 ngx_open_file_t
*file
;
51 ngx_listening_t
*ls
, *nls
;
53 ngx_core_module_t
*module
;
57 if (!(pool
= ngx_create_pool(16 * 1024, log
))) {
62 if (!(cycle
= ngx_pcalloc(pool
, sizeof(ngx_cycle_t
)))) {
63 ngx_destroy_pool(pool
);
68 cycle
->old_cycle
= old_cycle
;
69 cycle
->conf_file
= old_cycle
->conf_file
;
70 cycle
->root
.len
= sizeof(NGX_PREFIX
) - 1;
71 cycle
->root
.data
= (u_char
*) NGX_PREFIX
;
74 n
= old_cycle
->pathes
.nelts
? old_cycle
->pathes
.nelts
: 10;
75 if (!(cycle
->pathes
.elts
= ngx_pcalloc(pool
, n
* sizeof(ngx_path_t
*)))) {
76 ngx_destroy_pool(pool
);
79 cycle
->pathes
.nelts
= 0;
80 cycle
->pathes
.size
= sizeof(ngx_path_t
*);
81 cycle
->pathes
.nalloc
= n
;
82 cycle
->pathes
.pool
= pool
;
85 if (old_cycle
->open_files
.part
.nelts
) {
86 n
= old_cycle
->open_files
.part
.nelts
;
87 for (part
= old_cycle
->open_files
.part
.next
; part
; part
= part
->next
) {
95 if (ngx_list_init(&cycle
->open_files
, pool
, n
, sizeof(ngx_open_file_t
))
98 ngx_destroy_pool(pool
);
103 if (!(cycle
->new_log
= ngx_log_create_errlog(cycle
, NULL
))) {
104 ngx_destroy_pool(pool
);
108 cycle
->new_log
->file
->name
= error_log
;
111 n
= old_cycle
->listening
.nelts
? old_cycle
->listening
.nelts
: 10;
112 cycle
->listening
.elts
= ngx_pcalloc(pool
, n
* sizeof(ngx_listening_t
));
113 if (cycle
->listening
.elts
== NULL
) {
114 ngx_destroy_pool(pool
);
117 cycle
->listening
.nelts
= 0;
118 cycle
->listening
.size
= sizeof(ngx_listening_t
);
119 cycle
->listening
.nalloc
= n
;
120 cycle
->listening
.pool
= pool
;
123 cycle
->conf_ctx
= ngx_pcalloc(pool
, ngx_max_module
* sizeof(void *));
124 if (cycle
->conf_ctx
== NULL
) {
125 ngx_destroy_pool(pool
);
130 for (i
= 0; ngx_modules
[i
]; i
++) {
131 if (ngx_modules
[i
]->type
!= NGX_CORE_MODULE
) {
135 module
= ngx_modules
[i
]->ctx
;
137 if (module
->create_conf
) {
138 rv
= module
->create_conf(cycle
);
139 if (rv
== NGX_CONF_ERROR
) {
140 ngx_destroy_pool(pool
);
143 cycle
->conf_ctx
[ngx_modules
[i
]->index
] = rv
;
148 ngx_memzero(&conf
, sizeof(ngx_conf_t
));
149 /* STUB: init array ? */
150 conf
.args
= ngx_create_array(pool
, 10, sizeof(ngx_str_t
));
151 if (conf
.args
== NULL
) {
152 ngx_destroy_pool(pool
);
156 conf
.ctx
= cycle
->conf_ctx
;
160 conf
.module_type
= NGX_CORE_MODULE
;
161 conf
.cmd_type
= NGX_MAIN_CONF
;
164 log
->log_level
= NGX_LOG_DEBUG_ALL
;
167 if (ngx_conf_parse(&conf
, &cycle
->conf_file
) != NGX_CONF_OK
) {
168 ngx_destroy_pool(pool
);
172 if (ngx_test_config
) {
173 ngx_log_error(NGX_LOG_INFO
, log
, 0,
174 "the configuration file %s syntax is ok",
175 cycle
->conf_file
.data
);
179 for (i
= 0; ngx_modules
[i
]; i
++) {
180 if (ngx_modules
[i
]->type
!= NGX_CORE_MODULE
) {
184 module
= ngx_modules
[i
]->ctx
;
186 if (module
->init_conf
) {
187 if (module
->init_conf(cycle
, cycle
->conf_ctx
[ngx_modules
[i
]->index
])
190 ngx_destroy_pool(pool
);
201 if (ngx_create_pidfile(cycle
, old_cycle
) == NGX_ERROR
) {
208 ccf
= (ngx_core_conf_t
*) ngx_get_conf(cycle
->conf_ctx
,
211 if (ngx_create_pathes(cycle
, ccf
->user
) == NGX_ERROR
) {
219 /* open the new files */
221 part
= &cycle
->open_files
.part
;
224 for (i
= 0; /* void */ ; i
++) {
226 if (i
>= part
->nelts
) {
227 if (part
->next
== NULL
) {
235 if (file
[i
].name
.data
== NULL
) {
239 file
[i
].fd
= ngx_open_file(file
[i
].name
.data
,
241 NGX_FILE_CREATE_OR_OPEN
|NGX_FILE_APPEND
);
243 ngx_log_debug3(NGX_LOG_DEBUG_CORE
, log
, 0,
245 &file
[i
], file
[i
].fd
, file
[i
].name
.data
);
247 if (file
[i
].fd
== NGX_INVALID_FILE
) {
248 ngx_log_error(NGX_LOG_EMERG
, log
, ngx_errno
,
249 ngx_open_file_n
" \"%s\" failed",
256 if (ngx_file_append_mode(file
[i
].fd
) == NGX_ERROR
) {
257 ngx_log_error(NGX_LOG_EMERG
, log
, ngx_errno
,
258 ngx_file_append_mode_n
" \"%s\" failed",
264 if (fcntl(file
[i
].fd
, F_SETFD
, FD_CLOEXEC
) == -1) {
265 ngx_log_error(NGX_LOG_EMERG
, log
, ngx_errno
,
266 "fcntl(FD_CLOEXEC) \"%s\" failed",
275 cycle
->log
= cycle
->new_log
;
276 pool
->log
= cycle
->new_log
;
278 if (cycle
->log
->log_level
== 0) {
279 cycle
->log
->log_level
= NGX_LOG_ERR
;
284 /* handle the listening sockets */
286 if (old_cycle
->listening
.nelts
) {
287 ls
= old_cycle
->listening
.elts
;
288 for (i
= 0; i
< old_cycle
->listening
.nelts
; i
++) {
292 nls
= cycle
->listening
.elts
;
293 for (n
= 0; n
< cycle
->listening
.nelts
; n
++) {
295 for (i
= 0; i
< old_cycle
->listening
.nelts
; i
++) {
300 if (ngx_cmp_sockaddr(nls
[n
].sockaddr
, ls
[i
].sockaddr
)
306 * Winsock assignes a socket number divisible by 4 so
307 * to find a connection we divide a socket number by 4.
312 if (fd
>= (ngx_socket_t
) cycle
->connection_n
) {
313 ngx_log_error(NGX_LOG_EMERG
, log
, 0,
314 "%d connections is not enough to hold "
315 "an open listening socket on %V, "
316 "required at least %d connections",
318 &ls
[i
].addr_text
, fd
);
323 nls
[n
].fd
= ls
[i
].fd
;
330 if (nls
[n
].fd
== -1) {
336 ls
= cycle
->listening
.elts
;
337 for (i
= 0; i
< cycle
->listening
.nelts
; i
++) {
342 if (!ngx_test_config
&& !failed
) {
343 if (ngx_open_listening_sockets(cycle
) == NGX_ERROR
) {
351 /* rollback the new cycle configuration */
353 part
= &cycle
->open_files
.part
;
356 for (i
= 0; /* void */ ; i
++) {
358 if (i
>= part
->nelts
) {
359 if (part
->next
== NULL
) {
367 if (file
[i
].fd
== NGX_INVALID_FILE
368 || file
[i
].fd
== ngx_stderr_fileno
)
373 if (ngx_close_file(file
[i
].fd
) == NGX_FILE_ERROR
) {
374 ngx_log_error(NGX_LOG_EMERG
, log
, ngx_errno
,
375 ngx_close_file_n
" \"%s\" failed",
380 if (ngx_test_config
) {
381 ngx_destroy_pool(pool
);
385 ls
= cycle
->listening
.elts
;
386 for (i
= 0; i
< cycle
->listening
.nelts
; i
++) {
387 if (ls
[i
].fd
== -1 || !ls
[i
].open
) {
391 if (ngx_close_socket(ls
[i
].fd
) == -1) {
392 ngx_log_error(NGX_LOG_EMERG
, log
, ngx_socket_errno
,
393 ngx_close_socket_n
" %V failed",
398 ngx_destroy_pool(pool
);
403 /* commit the new cycle configuration */
407 if (!ngx_test_config
&& cycle
->log
->file
->fd
!= STDERR_FILENO
) {
409 ngx_log_debug3(NGX_LOG_DEBUG_CORE
, log
, 0,
410 "dup2: %p %d \"%s\"",
412 cycle
->log
->file
->fd
, cycle
->log
->file
->name
.data
);
414 if (dup2(cycle
->log
->file
->fd
, STDERR_FILENO
) == NGX_ERROR
) {
415 ngx_log_error(NGX_LOG_EMERG
, log
, ngx_errno
,
416 "dup2(STDERR) failed");
424 pool
->log
= cycle
->log
;
426 for (i
= 0; ngx_modules
[i
]; i
++) {
427 if (ngx_modules
[i
]->init_module
) {
428 if (ngx_modules
[i
]->init_module(cycle
) == NGX_ERROR
) {
436 /* close and delete stuff that lefts from an old cycle */
438 /* close the unneeded listening sockets */
440 ls
= old_cycle
->listening
.elts
;
441 for (i
= 0; i
< old_cycle
->listening
.nelts
; i
++) {
446 if (ngx_close_socket(ls
[i
].fd
) == -1) {
447 ngx_log_error(NGX_LOG_EMERG
, log
, ngx_socket_errno
,
448 ngx_close_socket_n
" %V failed",
454 /* close the unneeded open files */
456 part
= &old_cycle
->open_files
.part
;
459 for (i
= 0; /* void */ ; i
++) {
461 if (i
>= part
->nelts
) {
462 if (part
->next
== NULL
) {
470 if (file
[i
].fd
== NGX_INVALID_FILE
|| file
[i
].fd
== ngx_stderr_fileno
) {
474 if (ngx_close_file(file
[i
].fd
) == NGX_FILE_ERROR
) {
475 ngx_log_error(NGX_LOG_EMERG
, log
, ngx_errno
,
476 ngx_close_file_n
" \"%s\" failed",
481 if (old_cycle
->connections
== NULL
) {
482 /* an old cycle is an init cycle */
483 ngx_destroy_pool(old_cycle
->pool
);
487 if (ngx_process
== NGX_PROCESS_MASTER
) {
488 ngx_destroy_pool(old_cycle
->pool
);
492 if (ngx_temp_pool
== NULL
) {
493 ngx_temp_pool
= ngx_create_pool(128, cycle
->log
);
494 if (ngx_temp_pool
== NULL
) {
495 ngx_log_error(NGX_LOG_EMERG
, cycle
->log
, 0,
496 "can not create ngx_temp_pool");
501 ngx_old_cycles
.elts
= ngx_pcalloc(ngx_temp_pool
,
502 n
* sizeof(ngx_cycle_t
*));
503 if (ngx_old_cycles
.elts
== NULL
) {
506 ngx_old_cycles
.nelts
= 0;
507 ngx_old_cycles
.size
= sizeof(ngx_cycle_t
*);
508 ngx_old_cycles
.nalloc
= n
;
509 ngx_old_cycles
.pool
= ngx_temp_pool
;
511 ngx_cleaner_event
.event_handler
= ngx_clean_old_cycles
;
512 ngx_cleaner_event
.log
= cycle
->log
;
513 ngx_cleaner_event
.data
= &dumb
;
514 dumb
.fd
= (ngx_socket_t
) -1;
517 ngx_temp_pool
->log
= cycle
->log
;
519 old
= ngx_push_array(&ngx_old_cycles
);
525 if (!ngx_cleaner_event
.timer_set
) {
526 ngx_add_timer(&ngx_cleaner_event
, 30000);
527 ngx_cleaner_event
.timer_set
= 1;
534 static ngx_int_t
ngx_cmp_sockaddr(struct sockaddr
*sa1
, struct sockaddr
*sa2
)
536 struct sockaddr_in
*sin1
, *sin2
;
540 if (sa1
->sa_family
!= AF_INET
|| sa2
->sa_family
!= AF_INET
) {
544 sin1
= (struct sockaddr_in
*) sa1
;
545 sin2
= (struct sockaddr_in
*) sa2
;
547 if (sin1
->sin_addr
.s_addr
!= sin2
->sin_addr
.s_addr
) {
551 if (sin1
->sin_port
!= sin2
->sin_port
) {
561 ngx_int_t
ngx_create_pidfile(ngx_cycle_t
*cycle
, ngx_cycle_t
*old_cycle
)
565 u_char
*name
, pid
[NGX_INT64_LEN
];
567 ngx_core_conf_t
*ccf
, *old_ccf
;
569 if (!ngx_test_config
&& old_cycle
&& old_cycle
->conf_ctx
== NULL
) {
572 * do not create the pid file in the first ngx_init_cycle() call
573 * because we need to write the demonized process pid
579 ccf
= (ngx_core_conf_t
*) ngx_get_conf(cycle
->conf_ctx
, ngx_core_module
);
581 if (!ngx_test_config
&& old_cycle
) {
582 old_ccf
= (ngx_core_conf_t
*) ngx_get_conf(old_cycle
->conf_ctx
,
585 if (ccf
->pid
.len
== old_ccf
->pid
.len
586 && ngx_strcmp(ccf
->pid
.data
, old_ccf
->pid
.data
) == 0)
589 /* pid file name is the same */
595 ngx_memzero(&file
, sizeof(ngx_file_t
));
596 file
.name
= (ngx_inherited
&& getppid() > 1) ? ccf
->newpid
: ccf
->pid
;
597 file
.log
= cycle
->log
;
599 trunc
= ngx_test_config
? 0: NGX_FILE_TRUNCATE
;
601 file
.fd
= ngx_open_file(file
.name
.data
, NGX_FILE_RDWR
,
602 NGX_FILE_CREATE_OR_OPEN
|trunc
);
604 if (file
.fd
== NGX_INVALID_FILE
) {
605 ngx_log_error(NGX_LOG_EMERG
, cycle
->log
, ngx_errno
,
606 ngx_open_file_n
" \"%s\" failed", file
.name
.data
);
610 if (!ngx_test_config
) {
611 len
= ngx_sprintf(pid
, "%P", ngx_pid
) - pid
;
613 if (ngx_write_file(&file
, pid
, len
, 0) == NGX_ERROR
) {
618 if (ngx_close_file(file
.fd
) == NGX_FILE_ERROR
) {
619 ngx_log_error(NGX_LOG_ALERT
, cycle
->log
, ngx_errno
,
620 ngx_close_file_n
" \"%s\" failed", file
.name
.data
);
623 ngx_delete_pidfile(old_cycle
);
629 void ngx_delete_pidfile(ngx_cycle_t
*cycle
)
632 ngx_core_conf_t
*ccf
;
634 if (cycle
== NULL
|| cycle
->conf_ctx
== NULL
) {
638 ccf
= (ngx_core_conf_t
*) ngx_get_conf(cycle
->conf_ctx
, ngx_core_module
);
640 if (ngx_inherited
&& getppid() > 1) {
641 name
= ccf
->newpid
.data
;
644 name
= ccf
->pid
.data
;
647 if (ngx_delete_file(name
) == NGX_FILE_ERROR
) {
648 ngx_log_error(NGX_LOG_ALERT
, cycle
->log
, ngx_errno
,
649 ngx_delete_file_n
" \"%s\" failed", name
);
656 void ngx_reopen_files(ngx_cycle_t
*cycle
, ngx_uid_t user
)
660 ngx_list_part_t
*part
;
661 ngx_open_file_t
*file
;
666 part
= &cycle
->open_files
.part
;
669 for (i
= 0; /* void */ ; i
++) {
671 if (i
>= part
->nelts
) {
672 if (part
->next
== NULL
) {
679 if (file
[i
].name
.data
== NULL
) {
683 fd
= ngx_open_file(file
[i
].name
.data
, NGX_FILE_RDWR
,
684 NGX_FILE_CREATE_OR_OPEN
|NGX_FILE_APPEND
);
686 ngx_log_debug3(NGX_LOG_DEBUG_EVENT
, cycle
->log
, 0,
687 "reopen file \"%s\", old:%d new:%d",
688 file
[i
].name
.data
, file
[i
].fd
, fd
);
690 if (fd
== NGX_INVALID_FILE
) {
691 ngx_log_error(NGX_LOG_EMERG
, cycle
->log
, ngx_errno
,
692 ngx_open_file_n
" \"%s\" failed", file
[i
].name
.data
);
697 if (ngx_file_append_mode(fd
) == NGX_ERROR
) {
698 ngx_log_error(NGX_LOG_EMERG
, cycle
->log
, ngx_errno
,
699 ngx_file_append_mode_n
" \"%s\" failed",
702 if (ngx_close_file(fd
) == NGX_FILE_ERROR
) {
703 ngx_log_error(NGX_LOG_EMERG
, cycle
->log
, ngx_errno
,
704 ngx_close_file_n
" \"%s\" failed",
711 if (user
!= (ngx_uid_t
) -1) {
713 if (ngx_file_info((const char *) file
[i
].name
.data
, &fi
) == -1) {
714 ngx_log_error(NGX_LOG_EMERG
, cycle
->log
, ngx_errno
,
715 ngx_file_info_n
" \"%s\" failed",
718 if (ngx_close_file(fd
) == NGX_FILE_ERROR
) {
719 ngx_log_error(NGX_LOG_EMERG
, cycle
->log
, ngx_errno
,
720 ngx_close_file_n
" \"%s\" failed",
725 if (fi
.st_uid
!= user
) {
726 if (chown((const char *) file
[i
].name
.data
, user
, -1) == -1) {
727 ngx_log_error(NGX_LOG_EMERG
, cycle
->log
, ngx_errno
,
728 "chown(\"%s\", %d) failed",
729 file
[i
].name
.data
, user
);
731 if (ngx_close_file(fd
) == NGX_FILE_ERROR
) {
732 ngx_log_error(NGX_LOG_EMERG
, cycle
->log
, ngx_errno
,
733 ngx_close_file_n
" \"%s\" failed",
739 if ((fi
.st_mode
& (S_IRUSR
|S_IWUSR
)) != (S_IRUSR
|S_IWUSR
)) {
741 fi
.st_mode
|= (S_IRUSR
|S_IWUSR
);
743 if (chmod((const char *) file
[i
].name
.data
, fi
.st_mode
) == -1) {
744 ngx_log_error(NGX_LOG_EMERG
, cycle
->log
, ngx_errno
,
745 "chmod() \"%s\" failed", file
[i
].name
.data
);
747 if (ngx_close_file(fd
) == NGX_FILE_ERROR
) {
748 ngx_log_error(NGX_LOG_EMERG
, cycle
->log
, ngx_errno
,
749 ngx_close_file_n
" \"%s\" failed",
756 if (fcntl(fd
, F_SETFD
, FD_CLOEXEC
) == -1) {
757 ngx_log_error(NGX_LOG_EMERG
, cycle
->log
, ngx_errno
,
758 "fcntl(FD_CLOEXEC) \"%s\" failed",
761 if (ngx_close_file(fd
) == NGX_FILE_ERROR
) {
762 ngx_log_error(NGX_LOG_EMERG
, cycle
->log
, ngx_errno
,
763 ngx_close_file_n
" \"%s\" failed",
771 if (ngx_close_file(file
[i
].fd
) == NGX_FILE_ERROR
) {
772 ngx_log_error(NGX_LOG_EMERG
, cycle
->log
, ngx_errno
,
773 ngx_close_file_n
" \"%s\" failed",
782 if (cycle
->log
->file
->fd
!= STDERR_FILENO
) {
783 if (dup2(cycle
->log
->file
->fd
, STDERR_FILENO
) == -1) {
784 ngx_log_error(NGX_LOG_EMERG
, cycle
->log
, ngx_errno
,
785 "dup2(STDERR) failed");
793 static void ngx_clean_old_cycles(ngx_event_t
*ev
)
795 ngx_uint_t i
, n
, found
, live
;
799 log
= ngx_cycle
->log
;
800 ngx_temp_pool
->log
= log
;
802 ngx_log_debug0(NGX_LOG_DEBUG_CORE
, log
, 0, "clean old cycles");
806 cycle
= ngx_old_cycles
.elts
;
807 for (i
= 0; i
< ngx_old_cycles
.nelts
; i
++) {
809 if (cycle
[i
] == NULL
) {
815 for (n
= 0; n
< cycle
[i
]->connection_n
; n
++) {
816 if (cycle
[i
]->connections
[n
].fd
!= (ngx_socket_t
) -1) {
819 ngx_log_debug1(NGX_LOG_DEBUG_CORE
, log
, 0, "live fd:%d", n
);
830 ngx_log_debug1(NGX_LOG_DEBUG_CORE
, log
, 0, "clean old cycle: %d", i
);
832 ngx_destroy_pool(cycle
[i
]->pool
);
836 ngx_log_debug1(NGX_LOG_DEBUG_CORE
, log
, 0, "old cycles status: %d", live
);
839 ngx_add_timer(ev
, 30000);
842 ngx_destroy_pool(ngx_temp_pool
);
843 ngx_temp_pool
= NULL
;
844 ngx_old_cycles
.nelts
= 0;