5454#include "apr_poll.h"
5555#include "apr_ring.h"
5656#include "apr_queue.h"
57+ #include "apr_atomic.h"
5758#define APR_WANT_STRFUNC
5859#include "apr_want.h"
5960#include "apr_version.h"
@@ -502,6 +503,13 @@ static int child_fatal;
502503/* volatile because they're updated from a signal handler */
503504static int volatile shutdown_pending ;
504505static int volatile restart_pending ;
506+ ap_generation_t volatile ap_my_generation = 0 ;
507+ static apr_uint32_t connection_count = 0 ;
508+
509+ static apr_status_t decrement_connection_count (void * dummy ){
510+ apr_atomic_dec32 (& connection_count );
511+ return APR_SUCCESS ;
512+ }
505513
506514/*
507515 * ap_start_shutdown() and ap_start_restart(), below, are a first stab at
@@ -671,6 +679,8 @@ static int process_socket(apr_thread_t *thd, apr_pool_t * p, apr_socket_t * sock
671679 cs -> bucket_alloc = apr_bucket_alloc_create (p );
672680 c = ap_run_create_connection (p , ap_server_conf , sock ,
673681 conn_id , sbh , cs -> bucket_alloc );
682+ apr_atomic_inc32 (& connection_count );
683+ apr_pool_cleanup_register (c -> pool , NULL , decrement_connection_count , apr_pool_cleanup_null );
674684 c -> current_thread = thd ;
675685 cs -> c = c ;
676686 c -> cs = cs ;
@@ -832,6 +842,29 @@ static void check_infinite_requests(void)
832842 }
833843}
834844
845+ static void close_listeners (int process_slot , int * closed ) {
846+ if (!* closed ){
847+ ap_listen_rec * lr ;
848+ int i ;
849+ for (lr = ap_listeners ; lr != NULL ; lr = lr -> next ) {
850+ apr_pollfd_t * pfd = apr_pcalloc (pchild , sizeof (* pfd ));
851+ pfd -> desc_type = APR_POLL_SOCKET ;
852+ pfd -> desc .s = lr -> sd ;
853+ apr_pollset_remove (event_pollset , pfd );
854+ }
855+ ap_close_listeners ();
856+ * closed = 1 ;
857+ dying = 1 ;
858+ ap_scoreboard_image -> parent [process_slot ].quiescing = 1 ;
859+ for (i = 0 ; i < threads_per_child ; ++ i ){
860+ ap_update_child_status_from_indexes (process_slot , i ,
861+ SERVER_DEAD , NULL );
862+ }
863+ /* wake up the main thread */
864+ kill (ap_my_pid , SIGTERM );
865+ }
866+ }
867+
835868static void unblock_signal (int sig )
836869{
837870 sigset_t sig_mask ;
@@ -1082,6 +1115,7 @@ static void * APR_THREAD_FUNC listener_thread(apr_thread_t * thd, void *dummy)
10821115 apr_interval_time_t timeout_interval ;
10831116 apr_time_t timeout_time ;
10841117 listener_poll_type * pt ;
1118+ int closed = 0 ;
10851119
10861120 free (ti );
10871121
@@ -1108,7 +1142,13 @@ static void * APR_THREAD_FUNC listener_thread(apr_thread_t * thd, void *dummy)
11081142 unblock_signal (LISTENER_SIGNAL );
11091143 apr_signal (LISTENER_SIGNAL , dummy_signal_handler );
11101144
1111- while (!listener_may_exit ) {
1145+ for (;;) {
1146+ if (listener_may_exit ){
1147+ close_listeners (process_slot , & closed );
1148+ if (terminate_mode == ST_UNGRACEFUL
1149+ || apr_atomic_read32 (& connection_count ) == 0 )
1150+ break ;
1151+ }
11121152
11131153 if (requests_this_child <= 0 ) {
11141154 check_infinite_requests ();
@@ -1156,8 +1196,13 @@ static void * APR_THREAD_FUNC listener_thread(apr_thread_t * thd, void *dummy)
11561196 }
11571197 }
11581198
1159- if (listener_may_exit )
1160- break ;
1199+ if (listener_may_exit ){
1200+ close_listeners (process_slot , & closed );
1201+ if (terminate_mode == ST_UNGRACEFUL ||
1202+ apr_atomic_read32 (& connection_count ) == 0 ) {
1203+ break ;
1204+ }
1205+ }
11611206
11621207 {
11631208 apr_time_t now = apr_time_now ();
@@ -1353,13 +1398,8 @@ static void * APR_THREAD_FUNC listener_thread(apr_thread_t * thd, void *dummy)
13531398
13541399 } /* listener main loop */
13551400
1356- ap_close_listeners ( );
1401+ close_listeners ( process_slot , & closed );
13571402 ap_queue_term (worker_queue );
1358- dying = 1 ;
1359- ap_scoreboard_image -> parent [process_slot ].quiescing = 1 ;
1360-
1361- /* wake up the main thread */
1362- kill (ap_my_pid , SIGTERM );
13631403
13641404 apr_thread_exit (thd , APR_SUCCESS );
13651405 return NULL ;
@@ -1406,7 +1446,7 @@ static void *APR_THREAD_FUNC worker_thread(apr_thread_t * thd, void *dummy)
14061446 }
14071447
14081448 ap_update_child_status_from_indexes (process_slot , thread_slot ,
1409- SERVER_READY , NULL );
1449+ dying ? SERVER_DEAD : SERVER_READY , NULL );
14101450 worker_pop :
14111451 if (workers_may_exit ) {
14121452 break ;
@@ -1664,21 +1704,15 @@ static void join_workers(apr_thread_t * listener, apr_thread_t ** threads)
16641704 */
16651705
16661706 iter = 0 ;
1667- while (iter < 10 &&
1668- #ifdef HAVE_PTHREAD_KILL
1669- pthread_kill (* listener_os_thread , 0 )
1670- #else
1671- kill (ap_my_pid , 0 )
1672- #endif
1673- == 0 ) {
1674- /* listener not dead yet */
1707+ while (iter < 10 && !dying ) {
1708+ /* listener has not stopped accepting yet */
16751709 apr_sleep (apr_time_make (0 , 500000 ));
16761710 wakeup_listener ();
16771711 ++ iter ;
16781712 }
16791713 if (iter >= 10 ) {
16801714 ap_log_error (APLOG_MARK , APLOG_DEBUG , 0 , ap_server_conf ,
1681- "the listener thread didn't exit " );
1715+ "the listener thread didn't stop accepting " );
16821716 }
16831717 else {
16841718 rv = apr_thread_join (& thread_rv , listener );
0 commit comments