You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by yl...@apache.org on 2021/07/22 14:59:58 UTC
svn commit: r1891717 - /httpd/httpd/trunk/server/mpm/event/event.c
Author: ylavic
Date: Thu Jul 22 14:59:57 2021
New Revision: 1891717
URL: http://svn.apache.org/viewvc?rev=1891717&view=rev
Log:
mpm_event: handle lingering close fully in process_lingering_close().
* server/mpm/event/event.c (start_lingering_close_blocking): Axe the function
and put the code directly in process_lingering_close() on the first call when
cs->pub.state == CONN_STATE_LINGER, this simplifies lingering close handling
from process_socket() and event_resume_suspended().
No functional changes.
Follow up to r1891716.
Github: #208
Modified:
httpd/httpd/trunk/server/mpm/event/event.c
Modified: httpd/httpd/trunk/server/mpm/event/event.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/server/mpm/event/event.c?rev=1891717&r1=1891716&r2=1891717&view=diff
==============================================================================
--- httpd/httpd/trunk/server/mpm/event/event.c (original)
+++ httpd/httpd/trunk/server/mpm/event/event.c Thu Jul 22 14:59:57 2021
@@ -829,48 +829,6 @@ static void notify_resume(event_conn_sta
ap_run_resume_connection(cs->c, cs->r);
}
-static void close_connection(event_conn_state_t *cs);
-
-/*
- * Close our side of the connection, flushing data to the client first.
- * Pre-condition: cs is not in any timeout queue and not in the pollset,
- * timeout_mutex is not locked
- * return: 0 if connection is fully closed,
- * 1 if connection is lingering
- * May only be called by worker thread.
- */
-static int start_lingering_close_blocking(event_conn_state_t *cs)
-{
- apr_socket_t *csd = cs->pfd.desc.s;
-
- /* defer_lingering_close() may have bumped lingering_count already */
- if (!cs->deferred_linger) {
- apr_atomic_inc32(&lingering_count);
- }
-
- apr_socket_timeout_set(csd, apr_time_from_sec(SECONDS_TO_LINGER));
- if (ap_start_lingering_close(cs->c)) {
- notify_suspend(cs);
- close_connection(cs);
- return DONE;
- }
-
- cs->queue_timestamp = apr_time_now();
- /*
- * If some module requested a shortened waiting period, only wait for
- * 2s (SECONDS_TO_LINGER). This is useful for mitigating certain
- * DoS attacks.
- */
- if (apr_table_get(cs->c->notes, "short-lingering-close")) {
- cs->pub.state = CONN_STATE_LINGER_SHORT;
- }
- else {
- cs->pub.state = CONN_STATE_LINGER_NORMAL;
- }
- notify_suspend(cs);
- return OK;
-}
-
/*
* Defer flush and close of the connection by adding it to defer_linger_chain,
* for a worker to grab it and do the job (should that be blocking).
@@ -1279,12 +1237,10 @@ read_request:
return;
}
- if (cs->pub.state == CONN_STATE_LINGER) {
- rc = start_lingering_close_blocking(cs);
- }
- if (rc == OK && (cs->pub.state == CONN_STATE_LINGER_NORMAL ||
- cs->pub.state == CONN_STATE_LINGER_SHORT)) {
+ /* CONN_STATE_LINGER[_*] fall through process_lingering_close() */
+ if (cs->pub.state >= CONN_STATE_LINGER) {
process_lingering_close(cs);
+ return;
}
}
@@ -1304,14 +1260,7 @@ static apr_status_t event_resume_suspend
apr_atomic_dec32(&suspended_count);
c->suspended_baton = NULL;
- if (cs->pub.state == CONN_STATE_LINGER) {
- int rc = start_lingering_close_blocking(cs);
- if (rc == OK && (cs->pub.state == CONN_STATE_LINGER_NORMAL ||
- cs->pub.state == CONN_STATE_LINGER_SHORT)) {
- process_lingering_close(cs);
- }
- }
- else {
+ if (cs->pub.state < CONN_STATE_LINGER) {
cs->queue_timestamp = apr_time_now();
cs->pub.state = CONN_STATE_WRITE_COMPLETION;
notify_suspend(cs);
@@ -1322,6 +1271,10 @@ static apr_status_t event_resume_suspend
apr_pollset_add(event_pollset, &cs->pfd);
apr_thread_mutex_unlock(timeout_mutex);
}
+ else {
+ cs->pub.state = CONN_STATE_LINGER;
+ process_lingering_close(cs);
+ }
return OK;
}
@@ -1723,6 +1676,34 @@ static void process_lingering_close(even
"lingering close from state %i", (int)cs->pub.state);
AP_DEBUG_ASSERT(cs->pub.state >= CONN_STATE_LINGER);
+ 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);
+ }
+
+ apr_socket_timeout_set(csd, apr_time_from_sec(SECONDS_TO_LINGER));
+ if (ap_start_lingering_close(cs->c)) {
+ notify_suspend(cs);
+ close_connection(cs);
+ return;
+ }
+
+ cs->queue_timestamp = apr_time_now();
+ /*
+ * If some module requested a shortened waiting period, only wait for
+ * 2s (SECONDS_TO_LINGER). This is useful for mitigating certain
+ * DoS attacks.
+ */
+ if (apr_table_get(cs->c->notes, "short-lingering-close")) {
+ cs->pub.state = CONN_STATE_LINGER_SHORT;
+ }
+ else {
+ cs->pub.state = CONN_STATE_LINGER_NORMAL;
+ }
+ notify_suspend(cs);
+ }
+
apr_socket_timeout_set(csd, 0);
do {
nbytes = sizeof(dummybuf);