@ -12,15 +12,18 @@
static void ngx_start_worker_processes ( ngx_cycle_t * cycle , ngx_int_t n ,
ngx_int_t type ) ;
static void ngx_start_garbage_collector ( ngx_cycle_t * cycle , ngx_int_t type ) ;
static void ngx_signal_worker_processes ( ngx_cycle_t * cycle , int signo ) ;
static ngx_uint_t ngx_reap_childs ( ngx_cycle_t * cycle ) ;
static void ngx_master_exit ( ngx_cycle_t * cycle ) ;
static void ngx_worker_process_cycle ( ngx_cycle_t * cycle , void * data ) ;
static void ngx_worker_process_init ( ngx_cycle_t * cycle ) ;
static void ngx_channel_handler ( ngx_event_t * ev ) ;
# if (NGX_THREADS)
static void ngx_wakeup_worker_threads ( ngx_cycle_t * cycle ) ;
static void * ngx_worker_thread_cycle ( void * data ) ;
# endif
static void ngx_garbage_collector_cycle ( ngx_cycle_t * cycle , void * data ) ;
ngx_uint_t ngx_process ;
@ -109,6 +112,7 @@ void ngx_master_process_cycle(ngx_cycle_t *cycle)
ngx_start_worker_processes ( cycle , ccf - > worker_processes ,
NGX_PROCESS_RESPAWN ) ;
ngx_start_garbage_collector ( cycle , NGX_PROCESS_RESPAWN ) ;
ngx_new_binary = 0 ;
delay = 0 ;
@ -179,6 +183,7 @@ void ngx_master_process_cycle(ngx_cycle_t *cycle)
if ( ! ngx_noaccepting ) {
ngx_start_worker_processes ( cycle , ccf - > worker_processes ,
NGX_PROCESS_JUST_RESPAWN ) ;
ngx_start_garbage_collector ( cycle , NGX_PROCESS_JUST_RESPAWN ) ;
live = 1 ;
ngx_signal_worker_processes ( cycle ,
ngx_signal_value ( NGX_SHUTDOWN_SIGNAL ) ) ;
@ -193,6 +198,7 @@ void ngx_master_process_cycle(ngx_cycle_t *cycle)
ngx_start_worker_processes ( cycle , ccf - > worker_processes ,
NGX_PROCESS_RESPAWN ) ;
ngx_start_garbage_collector ( cycle , NGX_PROCESS_RESPAWN ) ;
ngx_noaccepting = 0 ;
continue ;
@ -211,6 +217,7 @@ void ngx_master_process_cycle(ngx_cycle_t *cycle)
ngx_core_module ) ;
ngx_start_worker_processes ( cycle , ccf - > worker_processes ,
NGX_PROCESS_JUST_RESPAWN ) ;
ngx_start_garbage_collector ( cycle , NGX_PROCESS_JUST_RESPAWN ) ;
live = 1 ;
ngx_signal_worker_processes ( cycle ,
ngx_signal_value ( NGX_SHUTDOWN_SIGNAL ) ) ;
@ -220,6 +227,7 @@ void ngx_master_process_cycle(ngx_cycle_t *cycle)
ngx_restart = 0 ;
ngx_start_worker_processes ( cycle , ccf - > worker_processes ,
NGX_PROCESS_RESPAWN ) ;
ngx_start_garbage_collector ( cycle , NGX_PROCESS_RESPAWN ) ;
live = 1 ;
}
@ -352,6 +360,47 @@ static void ngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t n,
}
static void ngx_start_garbage_collector ( ngx_cycle_t * cycle , ngx_int_t type )
{
ngx_int_t i ;
ngx_channel_t ch ;
return ;
ngx_log_error ( NGX_LOG_INFO , cycle - > log , 0 , " start garbage collector " ) ;
ch . command = NGX_CMD_OPEN_CHANNEL ;
ngx_spawn_process ( cycle , ngx_garbage_collector_cycle , NULL ,
" garbage collector " , type ) ;
ch . pid = ngx_processes [ ngx_process_slot ] . pid ;
ch . slot = ngx_process_slot ;
ch . fd = ngx_processes [ ngx_process_slot ] . channel [ 0 ] ;
for ( i = 0 ; i < ngx_last_process ; i + + ) {
if ( i = = ngx_process_slot
| | ngx_processes [ i ] . pid = = - 1
| | ngx_processes [ i ] . channel [ 0 ] = = - 1 )
{
continue ;
}
ngx_log_debug6 ( NGX_LOG_DEBUG_CORE , cycle - > log , 0 ,
" pass channel s:%d pid:%P fd:%d to s:%i pid:%P fd:%d " ,
ch . slot , ch . pid , ch . fd ,
i , ngx_processes [ i ] . pid ,
ngx_processes [ i ] . channel [ 0 ] ) ;
/* TODO: NGX_AGAIN */
ngx_write_channel ( ngx_processes [ i ] . channel [ 0 ] ,
& ch , sizeof ( ngx_channel_t ) , cycle - > log ) ;
}
}
static void ngx_signal_worker_processes ( ngx_cycle_t * cycle , int signo )
{
ngx_int_t i ;
@ -557,16 +606,120 @@ static void ngx_master_exit(ngx_cycle_t *cycle)
static void ngx_worker_process_cycle ( ngx_cycle_t * cycle , void * data )
{
ngx_worker_process_init ( cycle ) ;
ngx_setproctitle ( " worker process " ) ;
# if (NGX_THREADS)
if ( ngx_time_mutex_init ( cycle - > log ) = = NGX_ERROR ) {
/* fatal */
exit ( 2 ) ;
}
if ( ngx_threads_n ) {
if ( ngx_init_threads ( ngx_threads_n ,
ccf - > thread_stack_size , cycle ) = = NGX_ERROR )
{
/* fatal */
exit ( 2 ) ;
}
err = ngx_thread_key_create ( & ngx_core_tls_key ) ;
if ( err ! = 0 ) {
ngx_log_error ( NGX_LOG_ALERT , cycle - > log , err ,
ngx_thread_key_create_n " failed " ) ;
/* fatal */
exit ( 2 ) ;
}
for ( n = 0 ; n < ngx_threads_n ; n + + ) {
if ( ! ( ngx_threads [ n ] . cv = ngx_cond_init ( cycle - > log ) ) ) {
/* fatal */
exit ( 2 ) ;
}
if ( ngx_create_thread ( ( ngx_tid_t * ) & ngx_threads [ n ] . tid ,
ngx_worker_thread_cycle ,
( void * ) & ngx_threads [ n ] , cycle - > log ) ! = 0 )
{
/* fatal */
exit ( 2 ) ;
}
}
}
# endif
for ( ; ; ) {
if ( ngx_exiting
& & ngx_event_timer_rbtree = = & ngx_event_timer_sentinel )
{
ngx_log_error ( NGX_LOG_INFO , cycle - > log , 0 , " exiting " ) ;
# if (NGX_THREADS)
ngx_terminate = 1 ;
ngx_wakeup_worker_threads ( cycle ) ;
# endif
/*
* we do not destroy cycle - > pool here because a signal handler
* that uses cycle - > log can be called at this point
*/
exit ( 0 ) ;
}
ngx_log_debug0 ( NGX_LOG_DEBUG_EVENT , cycle - > log , 0 , " worker cycle " ) ;
ngx_process_events ( cycle ) ;
if ( ngx_terminate ) {
ngx_log_error ( NGX_LOG_INFO , cycle - > log , 0 , " exiting " ) ;
# if (NGX_THREADS)
ngx_wakeup_worker_threads ( cycle ) ;
# endif
/*
* we do not destroy cycle - > pool here because a signal handler
* that uses cycle - > log can be called at this point
*/
exit ( 0 ) ;
}
if ( ngx_quit ) {
ngx_quit = 0 ;
ngx_log_error ( NGX_LOG_INFO , cycle - > log , 0 ,
" gracefully shutting down " ) ;
ngx_setproctitle ( " worker process is shutting down " ) ;
if ( ! ngx_exiting ) {
ngx_close_listening_sockets ( cycle ) ;
ngx_exiting = 1 ;
}
}
if ( ngx_reopen ) {
ngx_reopen = 0 ;
ngx_log_error ( NGX_LOG_INFO , cycle - > log , 0 , " reopen logs " ) ;
ngx_reopen_files ( cycle , - 1 ) ;
}
}
}
static void ngx_worker_process_init ( ngx_cycle_t * cycle )
{
sigset_t set ;
ngx_err_t err ;
ngx_int_t n ;
ngx_uint_t i ;
struct timeval tv ;
ngx_listening_t * ls ;
ngx_core_conf_t * ccf ;
ngx_connection_t * c ;
ngx_listening_t * ls ;
ngx_gettimeofday ( & tv ) ;
@ -649,13 +802,13 @@ static void ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data)
if ( close ( ngx_processes [ n ] . channel [ 1 ] ) = = - 1 ) {
ngx_log_error ( NGX_LOG_ALERT , cycle - > log , ngx_errno ,
" close() failed " ) ;
" close() channel failed " ) ;
}
}
if ( close ( ngx_processes [ ngx_process_slot ] . channel [ 0 ] ) = = - 1 ) {
ngx_log_error ( NGX_LOG_ALERT , cycle - > log , ngx_errno ,
" close() failed " ) ;
" close() channel failed " ) ;
}
#if 0
@ -668,107 +821,6 @@ static void ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data)
/* fatal */
exit ( 2 ) ;
}
ngx_setproctitle ( " worker process " ) ;
# if (NGX_THREADS)
if ( ngx_time_mutex_init ( cycle - > log ) = = NGX_ERROR ) {
/* fatal */
exit ( 2 ) ;
}
if ( ngx_threads_n ) {
if ( ngx_init_threads ( ngx_threads_n ,
ccf - > thread_stack_size , cycle ) = = NGX_ERROR )
{
/* fatal */
exit ( 2 ) ;
}
err = ngx_thread_key_create ( & ngx_core_tls_key ) ;
if ( err ! = 0 ) {
ngx_log_error ( NGX_LOG_ALERT , cycle - > log , err ,
ngx_thread_key_create_n " failed " ) ;
/* fatal */
exit ( 2 ) ;
}
for ( n = 0 ; n < ngx_threads_n ; n + + ) {
if ( ! ( ngx_threads [ n ] . cv = ngx_cond_init ( cycle - > log ) ) ) {
/* fatal */
exit ( 2 ) ;
}
if ( ngx_create_thread ( ( ngx_tid_t * ) & ngx_threads [ n ] . tid ,
ngx_worker_thread_cycle ,
( void * ) & ngx_threads [ n ] , cycle - > log ) ! = 0 )
{
/* fatal */
exit ( 2 ) ;
}
}
}
# endif
for ( ; ; ) {
if ( ngx_exiting
& & ngx_event_timer_rbtree = = & ngx_event_timer_sentinel )
{
ngx_log_error ( NGX_LOG_INFO , cycle - > log , 0 , " exiting " ) ;
# if (NGX_THREADS)
ngx_terminate = 1 ;
ngx_wakeup_worker_threads ( cycle ) ;
# endif
/*
* we do not destroy cycle - > pool here because a signal handler
* that uses cycle - > log can be called at this point
*/
exit ( 0 ) ;
}
ngx_log_debug0 ( NGX_LOG_DEBUG_EVENT , cycle - > log , 0 , " worker cycle " ) ;
ngx_process_events ( cycle ) ;
if ( ngx_terminate ) {
ngx_log_error ( NGX_LOG_INFO , cycle - > log , 0 , " exiting " ) ;
# if (NGX_THREADS)
ngx_wakeup_worker_threads ( cycle ) ;
# endif
/*
* we do not destroy cycle - > pool here because a signal handler
* that uses cycle - > log can be called at this point
*/
exit ( 0 ) ;
}
if ( ngx_quit ) {
ngx_quit = 0 ;
ngx_log_error ( NGX_LOG_INFO , cycle - > log , 0 ,
" gracefully shutting down " ) ;
ngx_setproctitle ( " worker process is shutting down " ) ;
if ( ! ngx_exiting ) {
ngx_close_listening_sockets ( cycle ) ;
ngx_exiting = 1 ;
}
}
if ( ngx_reopen ) {
ngx_reopen = 0 ;
ngx_log_error ( NGX_LOG_INFO , cycle - > log , 0 , " reopen logs " ) ;
ngx_reopen_files ( cycle , - 1 ) ;
}
}
}
@ -778,6 +830,11 @@ static void ngx_channel_handler(ngx_event_t *ev)
ngx_channel_t ch ;
ngx_connection_t * c ;
if ( ev - > timedout ) {
ev - > timedout = 0 ;
return ;
}
c = ev - > data ;
ngx_log_debug0 ( NGX_LOG_DEBUG_CORE , ev - > log , 0 , " channel handler " ) ;
@ -834,7 +891,8 @@ static void ngx_channel_handler(ngx_event_t *ev)
ngx_processes [ ch . slot ] . channel [ 0 ] ) ;
if ( close ( ngx_processes [ ch . slot ] . channel [ 0 ] ) = = - 1 ) {
ngx_log_error ( NGX_LOG_ALERT , ev - > log , ngx_errno , " close() failed " ) ;
ngx_log_error ( NGX_LOG_ALERT , ev - > log , ngx_errno ,
" close() channel failed " ) ;
}
ngx_processes [ ch . slot ] . channel [ 0 ] = - 1 ;
@ -896,7 +954,6 @@ static void *ngx_worker_thread_cycle(void *data)
ngx_err_t err ;
ngx_core_tls_t * tls ;
ngx_cycle_t * cycle ;
struct timeval tv ;
thr - > cv - > tid = ngx_thread_self ( ) ;
@ -972,3 +1029,51 @@ static void *ngx_worker_thread_cycle(void *data)
}
# endif
static void ngx_garbage_collector_cycle ( ngx_cycle_t * cycle , void * data )
{
ngx_uint_t i ;
ngx_gc_t ctx ;
ngx_path_t * * path ;
ngx_event_t * ev ;
ngx_worker_process_init ( cycle ) ;
ev = & cycle - > read_events [ ngx_channel ] ;
ngx_accept_mutex = NULL ;
ngx_setproctitle ( " garbage collector " ) ;
#if 0
ngx_add_timer ( ev , 60 * 1000 ) ;
# endif
for ( ; ; ) {
if ( ngx_terminate | | ngx_quit ) {
ngx_log_error ( NGX_LOG_INFO , cycle - > log , 0 , " exiting " ) ;
exit ( 0 ) ;
}
if ( ngx_reopen ) {
ngx_reopen = 0 ;
ngx_log_error ( NGX_LOG_INFO , cycle - > log , 0 , " reopen logs " ) ;
ngx_reopen_files ( cycle , - 1 ) ;
}
path = cycle - > pathes . elts ;
for ( i = 0 ; i < cycle - > pathes . nelts ; i + + ) {
ctx . path = path [ i ] ;
ctx . log = cycle - > log ;
ctx . handler = path [ i ] - > gc_handler ;
ngx_collect_garbage ( & ctx , & path [ i ] - > name , 0 ) ;
}
ngx_add_timer ( ev , 60 * 60 * 1000 ) ;
ngx_process_events ( cycle ) ;
}
}