summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/httpd.h10
-rw-r--r--modules/http/http_request.c19
-rw-r--r--server/mpm/event/event.c2
-rw-r--r--server/mpm/motorz/motorz.c2
-rw-r--r--server/mpm/simple/simple_io.c2
-rw-r--r--server/util_filter.c8
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;
}