]> granicus.if.org Git - apache/commitdiff
* modules/proxy/proxy_http.c (ap_proxy_http_process_response): Use the
authorJoe Orton <jorton@apache.org>
Thu, 11 Nov 2004 19:49:56 +0000 (19:49 +0000)
committerJoe Orton <jorton@apache.org>
Thu, 11 Nov 2004 19:49:56 +0000 (19:49 +0000)
standard non-blocking-read/flush/blocking-read logic to ensure that
buffered content is flushed to the client if the next read will block.

PR: 19954

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@105751 13f79535-47bb-0310-9956-ffa450edef68

CHANGES
modules/proxy/proxy_http.c

diff --git a/CHANGES b/CHANGES
index e0c9f2a6927468c0cf70ef3208a5cbc7dc08e8e4..565c3894196cfc61ec8da211ff7ff83c2fe9a50b 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -2,6 +2,10 @@ Changes with Apache 2.1.0-dev
 
   [Remove entries to the current 2.0 section below, when backported]
 
+  *) mod_proxy_http: Stream content better - always flush buffered data to
+     the client before blocking waiting for new data.  PR 19954.
+     [Joe Orton]
+
   *) mod_ssl: Add support for command-line option "-t -DDUMP_CERTS" which
      will dump the filenames of all configured SSL certificates to stdout.
      [Joe Orton]
index f083971f1ea1505e0f0a0fb36a1da7546e4eccec..91b7875bf24bee2d293362ca04883232d98dfaa8 100644 (file)
@@ -1022,15 +1022,41 @@ apr_status_t ap_proxy_http_process_response(apr_pool_t * p, request_rec *r,
              * of the page into the brigade
              */
             if (conf->error_override == 0 || ap_is_HTTP_SUCCESS(r->status)) {
-
                 /* read the body, pass it to the output filters */
+                apr_read_type_e mode = APR_NONBLOCK_READ;
                 int finish = FALSE;
-                while (ap_get_brigade(rp->input_filters, 
-                                      bb, 
-                                      AP_MODE_READBYTES, 
-                                      APR_BLOCK_READ, 
-                                      conf->io_buffer_size) == APR_SUCCESS) {
+
+                do {
                     apr_off_t readbytes;
+                    apr_status_t rv;
+
+                    rv = ap_get_brigade(rp->input_filters, bb, 
+                                        AP_MODE_READBYTES, mode,
+                                        conf->io_buffer_size);
+
+                    /* ap_get_brigade will return success with an empty brigade
+                     * for a non-blocking read which would block: */
+                    if (APR_STATUS_IS_EAGAIN(rv)
+                        || (rv == APR_SUCCESS && APR_BRIGADE_EMPTY(bb))) {
+                        /* flush to the client and switch to blocking mode */
+                        e = apr_bucket_flush_create(c->bucket_alloc);
+                        APR_BRIGADE_INSERT_TAIL(bb, e);
+                        if (ap_pass_brigade(r->output_filters, bb)) {
+                            backend->close = 1;
+                            break;
+                        }
+                        apr_brigade_cleanup(bb);
+                        mode = APR_BLOCK_READ;
+                        continue;
+                    }
+                    else if (rv != APR_SUCCESS) {
+                        ap_log_cerror(APLOG_MARK, APLOG_ERR, rv, c,
+                                      "proxy: error reading response");
+                        break;
+                    }
+                    /* next time try a non-blocking read */
+                    mode = APR_NONBLOCK_READ;
+                    
                     apr_brigade_length(bb, 0, &readbytes);
                     backend->worker->s->readed += readbytes;
 #if DEBUGGING
@@ -1068,11 +1094,7 @@ apr_status_t ap_proxy_http_process_response(apr_pool_t * p, request_rec *r,
                     /* make sure we always clean up after ourselves */
                     apr_brigade_cleanup(bb);
 
-                    /* if we are done, leave */
-                    if (TRUE == finish) {
-                        break;
-                    }
-                }
+                } while (!finish);
             }
             ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
                          "proxy: end body send");