On 18 Nov 2013, at 1:24 PM, "Plüm, Rüdiger, Vodafone Group"
<[email protected]> wrote:
> + rv = send_brigade_nonblocking(net->client_socket, bb,
> + &(ctx->bytes_written), c);
> + if (APR_STATUS_IS_EAGAIN(rv)) {
> + setaside_remaining_output(f, ctx, bb, c);
> + }
> + else if (rv != APR_EAGAIN) {
>
> What if rv is APR_SUCCESS?
This is indeed broken, fixed.
Some more testing has revealed that mod_ssl's output filter breaks rules 2 and
5 of the 10 output filter rules published here:
http://httpd.apache.org/docs/trunk/da/developer/output-filters.html#rules
Instead of passing on all metadata buckets as required, mod_ssl only takes into
account EOS, EOC and FLUSH, and tries to consume metadata buckets as normal
data buckets. SSL_write() then sees the zero length write and treats it as a
noop. The core filter is never called, the event mpm interprets a non zero
c->data_in_output_filters as an invitation to try again, and we go into a spin.
If mod_ssl does this, we can expect other modules in the wild to be a problem.
A possible solution to this dilemma is to try and detect buggy filters and
compensate for the problem. We might have a protocol helper filter that run
early on and passes the brigade upstream. If we started with
c->data_in_output_filters as non zero and we are in WRITE_COMPLETION, and on
return the filter sees APR_SUCCESS from upstream, but c->data_in_output_filters
is still not zero, we may not have reached the core filter, so call the core
filter directly once with a nonblock bucket simulating the behaviour we have
now. This will ensure the setaside data in the core output filter will always
be written at least once on each call, preventing the spin. This path in theory
should only be followed if the buggy filter is present, because when the buggy
filter is not present and the core is successfully reached the return code will
be APR_EAGAIN, or APR_SUCCESS with c->data_in_output_filters going to zero.
Regards,
Graham
--