Ruediger Pluem wrote:
The logic in mod_proxy_http.c of 2.2.x already tries to address this issue by flushing the data if no more data is available from the backend right now:apr_read_type_e mode = APR_NONBLOCK_READ; int finish = FALSE; 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) || c->aborted) { backend->close = 1; break; } apr_brigade_cleanup(bb); mode = APR_BLOCK_READ; continue; } else if (rv == APR_EOF) { break; } 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; Anyway, it does not work as expected, as it seems that the condition (APR_STATUS_IS_EAGAIN(rv) || (rv == APR_SUCCESS && APR_BRIGADE_EMPTY(bb))) { never gets true.
I think this if statement covers the case where a non blocking read is attempted, and zero bytes are returned, in which case another non blocking read might also return zero bytes, causing the loop to spin at 100% processor usage.
The problem lies in the code further down: /* try send what we read */if (ap_pass_brigade(r->output_filters, bb) != APR_SUCCESS
|| c->aborted) { /* Ack! Phbtt! Die! User aborted! */backend->close = 1; /* this causes socket close below *
/ finish = TRUE; }Without explicitly adding flush buckets to the output filter stack, the output filter stack seems to buffer before sending (rational behaviour).
To change this, we would need to add an output flush bucket after each read.Is this a rational thing to do in the general case? Or should the addition of the flush be configurable?
Regards, Graham --
smime.p7s
Description: S/MIME Cryptographic Signature