Skip to content

Commit 8f58978

Browse files
author
Stefan Fritsch
committed
Fix graceful restart aborting connections
PR: 43359 Submitted by: Takashi Sato <takashi lans-tv com> git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1137182 13f79535-47bb-0310-9956-ffa450edef68
1 parent 8a3eaee commit 8f58978

2 files changed

Lines changed: 56 additions & 19 deletions

File tree

CHANGES

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
Changes with Apache 2.3.13
44

5+
*) mpm_event: Fix graceful restart aborting connections. PR 43359.
6+
[Takashi Sato <takashi lans-tv com>]
7+
58
*) mod_ssl: Disable AECDH ciphers in example config. PR 51363.
69
[Rob Stradling <rob comodo com>]
710

server/mpm/event/event.c

Lines changed: 53 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
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 */
503504
static int volatile shutdown_pending;
504505
static 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+
835868
static 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

Comments
 (0)