summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--server/mpm/event/event.c23
1 files changed, 15 insertions, 8 deletions
diff --git a/server/mpm/event/event.c b/server/mpm/event/event.c
index 0e6ce8a2ee..403f9a3c93 100644
--- a/server/mpm/event/event.c
+++ b/server/mpm/event/event.c
@@ -152,6 +152,8 @@
#define apr_time_from_msec(x) (x * 1000)
#endif
+#define CONN_STATE_IS_LINGERING_CLOSE(s) ((s) >= CONN_STATE_LINGER && \
+ (s) <= CONN_STATE_LINGER_SHORT)
#ifndef MAX_SECS_TO_LINGER
#define MAX_SECS_TO_LINGER 30
#endif
@@ -252,8 +254,11 @@ struct event_conn_state_t {
conn_state_t pub;
/** chaining in defer_linger_chain */
struct event_conn_state_t *chain;
- /** Is lingering close from defer_lingering_close()? */
- int deferred_linger;
+ unsigned int
+ /** Is lingering close from defer_lingering_close()? */
+ deferred_linger :1,
+ /** Has ap_start_lingering_close() been called? */
+ linger_started :1;
};
APR_RING_HEAD(timeout_head_t, event_conn_state_t);
@@ -933,7 +938,7 @@ static void close_connection(event_conn_state_t *cs)
*/
static int shutdown_connection(event_conn_state_t *cs)
{
- if (cs->pub.state < CONN_STATE_LINGER) {
+ if (!CONN_STATE_IS_LINGERING_CLOSE(cs->pub.state)) {
apr_table_setn(cs->c->notes, "short-lingering-close", "1");
defer_lingering_close(cs);
}
@@ -1114,7 +1119,7 @@ static void process_socket(apr_thread_t *thd, apr_pool_t * p, apr_socket_t * soc
c->id = conn_id;
}
- if (cs->pub.state >= CONN_STATE_LINGER) {
+ if (CONN_STATE_IS_LINGERING_CLOSE(cs->pub.state)) {
goto lingering_close;
}
@@ -1349,7 +1354,7 @@ static apr_status_t event_resume_suspended (conn_rec *c)
apr_atomic_dec32(&suspended_count);
c->suspended_baton = NULL;
- if (cs->pub.state < CONN_STATE_LINGER) {
+ if (!CONN_STATE_IS_LINGERING_CLOSE(cs->pub.state)) {
cs->queue_timestamp = apr_time_now();
notify_suspend(cs);
@@ -1362,7 +1367,6 @@ static apr_status_t event_resume_suspended (conn_rec *c)
apr_thread_mutex_unlock(timeout_mutex);
}
else {
- cs->pub.state = CONN_STATE_LINGER;
process_lingering_close(cs);
}
@@ -1769,9 +1773,12 @@ static void process_lingering_close(event_conn_state_t *cs)
ap_log_cerror(APLOG_MARK, APLOG_TRACE6, 0, cs->c,
"lingering close from state %i", (int)cs->pub.state);
- AP_DEBUG_ASSERT(cs->pub.state >= CONN_STATE_LINGER);
+ AP_DEBUG_ASSERT(CONN_STATE_IS_LINGERING_CLOSE(cs->pub.state));
+
+ if (!cs->linger_started) {
+ cs->pub.state = CONN_STATE_LINGER;
+ cs->linger_started = 1;
- if (cs->pub.state == CONN_STATE_LINGER) {
/* defer_lingering_close() may have bumped lingering_count already */
if (!cs->deferred_linger) {
apr_atomic_inc32(&lingering_count);