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 2022/03/07 13:19:37 UTC

svn commit: r1898683 - in /httpd/httpd/trunk: changes-entries/discard_body.diff modules/http/http_filters.c server/protocol.c

Author: ylavic
Date: Mon Mar  7 13:19:37 2022
New Revision: 1898683

URL: http://svn.apache.org/viewvc?rev=1898683&view=rev
Log:
core: Simpler connection close logic if discarding the request body fails.

If ap_discard_request_body() sets AP_CONN_CLOSE by itself it simplifies and
allows to consolidate end_output_stream() and error_output_stream().


Added:
    httpd/httpd/trunk/changes-entries/discard_body.diff
Modified:
    httpd/httpd/trunk/modules/http/http_filters.c
    httpd/httpd/trunk/server/protocol.c

Added: httpd/httpd/trunk/changes-entries/discard_body.diff
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/changes-entries/discard_body.diff?rev=1898683&view=auto
==============================================================================
--- httpd/httpd/trunk/changes-entries/discard_body.diff (added)
+++ httpd/httpd/trunk/changes-entries/discard_body.diff Mon Mar  7 13:19:37 2022
@@ -0,0 +1,2 @@
+  *) core: Simpler connection close logic if discarding the request body fails.
+     [Yann Ylavic, Ruediger Pluem]
\ No newline at end of file

Modified: httpd/httpd/trunk/modules/http/http_filters.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http/http_filters.c?rev=1898683&r1=1898682&r2=1898683&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http/http_filters.c (original)
+++ httpd/httpd/trunk/modules/http/http_filters.c Mon Mar  7 13:19:37 2022
@@ -1533,9 +1533,9 @@ AP_DECLARE(int) ap_map_http_request_erro
  */
 AP_DECLARE(int) ap_discard_request_body(request_rec *r)
 {
+    int rc = OK;
+    conn_rec *c = r->connection;
     apr_bucket_brigade *bb;
-    int seen_eos;
-    apr_status_t rv;
 
     /* Sometimes we'll get in a state where the input handling has
      * detected an error where we want to drop the connection, so if
@@ -1544,54 +1544,57 @@ AP_DECLARE(int) ap_discard_request_body(
      *
      * This function is also a no-op on a subrequest.
      */
-    if (r->main || r->connection->keepalive == AP_CONN_CLOSE ||
-        ap_status_drops_connection(r->status)) {
+    if (r->main || c->keepalive == AP_CONN_CLOSE) {
+        return OK;
+    }
+    if (ap_status_drops_connection(r->status)) {
+        c->keepalive = AP_CONN_CLOSE;
         return OK;
     }
 
     bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
-    seen_eos = 0;
-    do {
-        apr_bucket *bucket;
+    for (;;) {
+        apr_status_t rv;
 
         rv = ap_get_brigade(r->input_filters, bb, AP_MODE_READBYTES,
                             APR_BLOCK_READ, HUGE_STRING_LEN);
-
         if (rv != APR_SUCCESS) {
-            apr_brigade_destroy(bb);
-            return ap_map_http_request_error(rv, HTTP_BAD_REQUEST);
+            rc = ap_map_http_request_error(rv, HTTP_BAD_REQUEST);
+            goto cleanup;
         }
 
-        for (bucket = APR_BRIGADE_FIRST(bb);
-             bucket != APR_BRIGADE_SENTINEL(bb);
-             bucket = APR_BUCKET_NEXT(bucket))
-        {
-            const char *data;
-            apr_size_t len;
-
-            if (APR_BUCKET_IS_EOS(bucket)) {
-                seen_eos = 1;
-                break;
-            }
+        while (!APR_BRIGADE_EMPTY(bb)) {
+            apr_bucket *b = APR_BRIGADE_FIRST(bb);
 
-            /* These are metadata buckets. */
-            if (bucket->length == 0) {
-                continue;
+            if (APR_BUCKET_IS_EOS(b)) {
+                goto cleanup;
             }
 
-            /* We MUST read because in case we have an unknown-length
-             * bucket or one that morphs, we want to exhaust it.
+            /* There is no need to read empty or metadata buckets or
+             * buckets of known length, but we MUST read buckets of
+             * unknown length in order to exhaust them.
              */
-            rv = apr_bucket_read(bucket, &data, &len, APR_BLOCK_READ);
-            if (rv != APR_SUCCESS) {
-                apr_brigade_destroy(bb);
-                return HTTP_BAD_REQUEST;
+            if (b->length == (apr_size_t)-1) {
+                apr_size_t len;
+                const char *data;
+
+                rv = apr_bucket_read(b, &data, &len, APR_BLOCK_READ);
+                if (rv != APR_SUCCESS) {
+                    rc = HTTP_BAD_REQUEST;
+                    goto cleanup;
+                }
             }
+
+            apr_bucket_delete(b);
         }
-        apr_brigade_cleanup(bb);
-    } while (!seen_eos);
+    }
 
-    return OK;
+cleanup:
+    apr_brigade_cleanup(bb);
+    if (rc != OK) {
+        c->keepalive = AP_CONN_CLOSE;
+    }
+    return rc;
 }
 
 /* Here we deal with getting the request message body from the client.

Modified: httpd/httpd/trunk/server/protocol.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/server/protocol.c?rev=1898683&r1=1898682&r2=1898683&view=diff
==============================================================================
--- httpd/httpd/trunk/server/protocol.c (original)
+++ httpd/httpd/trunk/server/protocol.c Mon Mar  7 13:19:37 2022
@@ -1734,38 +1734,29 @@ AP_DECLARE(void) ap_set_sub_req_protocol
     rnew->main = (request_rec *) r;
 }
 
-static void error_output_stream(request_rec *r, int status)
+static void end_output_stream(request_rec *r, int status)
 {
     conn_rec *c = r->connection;
     apr_bucket_brigade *bb;
     apr_bucket *b;
 
     bb = apr_brigade_create(r->pool, c->bucket_alloc);
-    b = ap_bucket_error_create(status, NULL, r->pool,
-            r->connection->bucket_alloc);
-    APR_BRIGADE_INSERT_TAIL(bb, b);
+    if (status != OK) {
+        b = ap_bucket_error_create(status, NULL, r->pool, c->bucket_alloc);
+        APR_BRIGADE_INSERT_TAIL(bb, b);
+    }
     b = apr_bucket_eos_create(c->bucket_alloc);
     APR_BRIGADE_INSERT_TAIL(bb, b);
-    ap_pass_brigade(r->output_filters, bb);
-}
 
-static void end_output_stream(request_rec *r)
-{
-    conn_rec *c = r->connection;
-    apr_bucket_brigade *bb;
-    apr_bucket *b;
-
-    bb = apr_brigade_create(r->pool, c->bucket_alloc);
-    b = apr_bucket_eos_create(c->bucket_alloc);
-    APR_BRIGADE_INSERT_TAIL(bb, b);
     ap_pass_brigade(r->output_filters, bb);
+    apr_brigade_cleanup(bb);
 }
 
 AP_DECLARE(void) ap_finalize_sub_req_protocol(request_rec *sub)
 {
     /* tell the filter chain there is no more content coming */
     if (!sub->eos_sent) {
-        end_output_stream(sub);
+        end_output_stream(sub, OK);
     }
 }
 
@@ -1779,11 +1770,8 @@ AP_DECLARE(void) ap_finalize_request_pro
     int status = ap_discard_request_body(r);
 
     /* tell the filter chain there is no more content coming */
-    if (status) {
-        error_output_stream(r, status);
-    }
     if (!r->eos_sent) {
-        end_output_stream(r);
+        end_output_stream(r, status);
     }
 }