Straightforward for ap_filter_input_pending() since c->data_in_input_filter is
always checked wherever ap_run_input_pending(c) is.
For ap_filter_output_pending(), this allows to set c->data_in_output_filter in
ap_process_request_after_handler() and avoid an useless flush from mpm_event.
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@
1836239 13f79535-47bb-0310-9956-
ffa450edef68
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
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);
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);
|| 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;
}
|| 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;
}
|| 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 {
apr_bucket_brigade *bb;
ap_filter_t *f;
+ if (c->data_in_output_filters) {
+ return OK;
+ }
+
if (!c->pending_filters) {
return DECLINED;
}
{
ap_filter_t *f;
+ if (c->data_in_input_filters) {
+ return OK;
+ }
+
if (!c->pending_filters) {
return DECLINED;
}