diff options
-rw-r--r-- | include/httpd.h | 10 | ||||
-rw-r--r-- | modules/http/http_request.c | 19 | ||||
-rw-r--r-- | server/mpm/event/event.c | 2 | ||||
-rw-r--r-- | server/mpm/motorz/motorz.c | 2 | ||||
-rw-r--r-- | server/mpm/simple/simple_io.c | 2 | ||||
-rw-r--r-- | server/util_filter.c | 8 |
6 files changed, 34 insertions, 9 deletions
diff --git a/include/httpd.h b/include/httpd.h index 22b1a99ebc..33c7361991 100644 --- a/include/httpd.h +++ b/include/httpd.h @@ -1163,9 +1163,15 @@ struct conn_rec { struct apr_bucket_alloc_t *bucket_alloc; /** The current state of this connection; may be NULL if not used by MPM */ conn_state_t *cs; - /** Is there data pending in the input filters or connection? */ + /** Used internally to force ap_filter_input_pending() decision, + * the public interface is ap_filter_should_yield(c->input_filters) + * or ap_filter_input_pending(). + */ int data_in_input_filters; - /** No longer used, replaced with ap_filter_should_yield() */ + /** Used internally to force ap_filter_output_pending() decision, + * the public interface is ap_filter_should_yield(c->output_filters) + * or ap_filter_output_pending(). + */ int data_in_output_filters; /** Are there any filters that clogg/buffer the input stream, breaking diff --git a/modules/http/http_request.c b/modules/http/http_request.c index ac8944b865..f8022e892a 100644 --- a/modules/http/http_request.c +++ b/modules/http/http_request.c @@ -403,9 +403,20 @@ AP_DECLARE(void) ap_process_request_after_handler(request_rec *r) c->data_in_input_filters = (rv == APR_SUCCESS); apr_brigade_cleanup(bb); - if (c->cs) - c->cs->state = (c->aborted) ? CONN_STATE_LINGER - : CONN_STATE_WRITE_COMPLETION; + if (c->cs) { + if (c->aborted) { + c->cs->state = CONN_STATE_LINGER; + } + else { + /* If we have still data in the output filters here it means that + * the last (recent) nonblocking write was EAGAIN, so tell the MPM + * to not try another useless/stressful one but to go straight to + * POLLOUT. + */ + c->data_in_output_filters = ap_filter_should_yield(c->output_filters); + c->cs->state = CONN_STATE_WRITE_COMPLETION; + } + } AP_PROCESS_REQUEST_RETURN((uintptr_t)r, r->uri, r->status); if (ap_extended_status) { ap_time_process_request(c->sbh, STOP_PREQUEST); @@ -494,7 +505,7 @@ AP_DECLARE(void) ap_process_request(request_rec *r) ap_process_async_request(r); - if (!c->data_in_input_filters || ap_run_input_pending(c) != OK) { + if (ap_run_input_pending(c) != OK) { bb = ap_reuse_brigade_from_pool("ap_pr_bb", c->pool, c->bucket_alloc); b = apr_bucket_flush_create(c->bucket_alloc); APR_BRIGADE_INSERT_HEAD(bb, b); diff --git a/server/mpm/event/event.c b/server/mpm/event/event.c index fd60a57d99..fcc42a64c9 100644 --- a/server/mpm/event/event.c +++ b/server/mpm/event/event.c @@ -1187,7 +1187,7 @@ read_request: || listener_may_exit) { cs->pub.state = CONN_STATE_LINGER; } - else if (c->data_in_input_filters || ap_run_input_pending(c) == OK) { + else if (ap_run_input_pending(c) == OK) { cs->pub.state = CONN_STATE_READ_REQUEST_LINE; goto read_request; } diff --git a/server/mpm/motorz/motorz.c b/server/mpm/motorz/motorz.c index be8f3020e4..f3a543e798 100644 --- a/server/mpm/motorz/motorz.c +++ b/server/mpm/motorz/motorz.c @@ -438,7 +438,7 @@ read_request: || c->aborted) { scon->cs.state = CONN_STATE_LINGER; } - else if (c->data_in_input_filters || ap_run_input_pending(c) == OK) { + else if (ap_run_input_pending(c) == OK) { scon->cs.state = CONN_STATE_READ_REQUEST_LINE; goto read_request; } diff --git a/server/mpm/simple/simple_io.c b/server/mpm/simple/simple_io.c index 19f5af136b..ff94aea281 100644 --- a/server/mpm/simple/simple_io.c +++ b/server/mpm/simple/simple_io.c @@ -131,7 +131,7 @@ static apr_status_t simple_io_process(simple_conn_t * scon) || c->aborted) { scon->cs.state = CONN_STATE_LINGER; } - else if (c->data_in_input_filters || ap_run_input_pending(c) == OK) { + else if (ap_run_input_pending(c) == OK) { scon->cs.state = CONN_STATE_READ_REQUEST_LINE; } else { diff --git a/server/util_filter.c b/server/util_filter.c index 470547c37e..22af83d8bc 100644 --- a/server/util_filter.c +++ b/server/util_filter.c @@ -1008,6 +1008,10 @@ AP_DECLARE_NONSTD(int) ap_filter_output_pending(conn_rec *c) apr_bucket_brigade *bb; ap_filter_t *f; + if (c->data_in_output_filters) { + return OK; + } + if (!c->pending_filters) { return DECLINED; } @@ -1044,6 +1048,10 @@ AP_DECLARE_NONSTD(int) ap_filter_input_pending(conn_rec *c) { ap_filter_t *f; + if (c->data_in_input_filters) { + return OK; + } + if (!c->pending_filters) { return DECLINED; } |