Hello all,

I've submitted a pull request on GitHub here:
https://github.com/apache/httpd/pull/387, per the instructions I found
at https://httpd.apache.org/contribute. I figured it may also be
useful to share the patch here, but please feel free to redirect me as
this is my first time contributing.

Thanks!

Eric Norris
Etsy

---

At Etsy, we use mod_php and were investigating what we thought was
surprising behavior - that code executed during PHP's shutdown phase
prevented the request from terminating, even if we didn't expect to send
any additional output to the client.

We determined that this was not surprising given mod_php's
implementation, but after we developed a proof-of-concept patch that
sent an EOS bucket and a flush bucket via a "userland" PHP function, we
were surprised that it didn't work when compression was enabled for the
request.

I was able to reproduce this behavior with a simple Apache module built
on top of mod_example_hooks:

https://gist.github.com/ericnorris/37c7dac401b50d270867e82a47bdd294

It seems that this is because mod_deflate receives the EOS bucket and
then calls `deflateEnd` but remains in the filter chain. This means that
it receives the next flush bucket and attempts to call
`flush_libz_buffer`, which of course fails, causing it to print an
AH01385 error to the Apache error log, and perhaps most importantly, to
"eat" the flush bucket and not pass it down the bucket brigade.

We found that this patch allows us to successfully send an EOS bucket
*and* promptly flush the connection so that the client knows the request
is finished.
---
 modules/filters/mod_deflate.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/modules/filters/mod_deflate.c b/modules/filters/mod_deflate.c
index b7a68d2d43..ad753dc618 100644
--- a/modules/filters/mod_deflate.c
+++ b/modules/filters/mod_deflate.c
@@ -941,6 +941,10 @@ static apr_status_t deflate_out_filter(ap_filter_t *f,
             }

             deflateEnd(&ctx->stream);
+
+            /* We've ended the libz stream, so remove ourselves. */
+            ap_remove_output_filter(f);
+
             /* No need for cleanup any longer */
             apr_pool_cleanup_kill(r->pool, ctx, deflate_ctx_cleanup);

--
2.40.1

Reply via email to