Index: include/httpd.h
===================================================================
--- include/httpd.h	(revision 1622873)
+++ include/httpd.h	(working copy)
@@ -1181,6 +1181,12 @@
 
     /** Context under which this connection was suspended */
     void *suspended_baton;
+
+    /** Activity marker for this connection */
+    unsigned int activity;
+
+    /** Empty bucket brigade */
+    apr_bucket_brigade *empty;
 };
 
 struct conn_slave_rec {
Index: server/core.c
===================================================================
--- server/core.c	(revision 1622873)
+++ server/core.c	(working copy)
@@ -4888,6 +4888,7 @@
 
     c->id = id;
     c->bucket_alloc = alloc;
+    c->empty = apr_brigade_create(c->pool, c->bucket_alloc);
 
     c->clogging_input_filters = 0;
 
Index: server/core_filters.c
===================================================================
--- server/core_filters.c	(revision 1622873)
+++ server/core_filters.c	(working copy)
@@ -368,23 +368,20 @@
  */
 extern APR_OPTIONAL_FN_TYPE(ap_logio_add_bytes_out) *ap__logio_add_bytes_out;
 
-apr_status_t ap_core_output_filter(ap_filter_t *f, apr_bucket_brigade *new_bb)
+apr_status_t ap_core_output_filter(ap_filter_t *f, apr_bucket_brigade *bb)
 {
     conn_rec *c = f->c;
     core_net_rec *net = f->ctx;
     core_output_filter_ctx_t *ctx = net->out_ctx;
-    apr_bucket_brigade *bb = NULL;
     apr_bucket *bucket, *next, *flush_upto = NULL;
     apr_size_t bytes_in_brigade, non_file_bytes_in_brigade;
     int eor_buckets_in_brigade, morphing_bucket_in_brigade;
-    apr_status_t rv;
+    apr_status_t rv, empty;
     int loglevel = ap_get_conn_module_loglevel(c, APLOG_MODULE_INDEX);
 
     /* Fail quickly if the connection has already been aborted. */
     if (c->aborted) {
-        if (new_bb != NULL) {
-            apr_brigade_cleanup(new_bb);
-        }
+        apr_brigade_cleanup(bb);
         return APR_ECONNABORTED;
     }
 
@@ -401,29 +398,22 @@
         ctx->buffered_bb = apr_brigade_create(c->pool, c->bucket_alloc);
     }
 
-    if (new_bb != NULL)
-        bb = new_bb;
+    empty = APR_BRIGADE_EMPTY(bb);
 
-    if ((ctx->buffered_bb != NULL) &&
-        !APR_BRIGADE_EMPTY(ctx->buffered_bb)) {
-        if (new_bb != NULL) {
-            APR_BRIGADE_PREPEND(bb, ctx->buffered_bb);
-        }
-        else {
-            bb = ctx->buffered_bb;
-        }
+    if ((ctx->buffered_bb != NULL) && !APR_BRIGADE_EMPTY(ctx->buffered_bb)) {
+        APR_BRIGADE_PREPEND(bb, ctx->buffered_bb);
         c->data_in_output_filters = 0;
     }
-    else if (new_bb == NULL) {
+    else if (empty) {
         return APR_SUCCESS;
     }
 
     /* Scan through the brigade and decide whether to attempt a write,
      * and how much to write, based on the following rules:
      *
-     *  1) The new_bb is null: Do a nonblocking write of as much as
+     *  1) The bb is empty: Do a nonblocking write of as much as
      *     possible: do a nonblocking write of as much data as possible,
-     *     then save the rest in ctx->buffered_bb.  (If new_bb == NULL,
+     *     then save the rest in ctx->buffered_bb.  (If bb is empty,
      *     it probably means that the MPM is doing asynchronous write
      *     completion and has just determined that this connection
      *     is writable.)
@@ -465,7 +455,7 @@
      *     then save the rest in ctx->buffered_bb.
      */
 
-    if (new_bb == NULL) {
+    if (empty) {
         rv = send_brigade_nonblocking(net->client_socket, bb,
                                       &(ctx->bytes_written), c);
         if (APR_STATUS_IS_EAGAIN(rv)) {
Index: server/mpm/event/event.c
===================================================================
--- server/mpm/event/event.c	(revision 1622873)
+++ server/mpm/event/event.c	(working copy)
@@ -1090,10 +1090,10 @@
         ap_filter_t *output_filter = c->output_filters;
         apr_status_t rv;
         ap_update_child_status_from_conn(sbh, SERVER_BUSY_WRITE, c);
-        while (output_filter->next != NULL) {
-            output_filter = output_filter->next;
-        }
-        rv = output_filter->frec->filter_func.out_func(output_filter, NULL);
+
+        rv = ap_pass_brigade(output_filter, c->empty);
+        apr_brigade_cleanup(c->empty);
+
         if (rv != APR_SUCCESS) {
             ap_log_cerror(APLOG_MARK, APLOG_DEBUG, rv, c, APLOGNO(00470)
                           "network write failure in core output filter");
Index: server/util_filter.c
===================================================================
--- server/util_filter.c	(revision 1622873)
+++ server/util_filter.c	(working copy)
@@ -566,6 +566,16 @@
 {
     if (next) {
         apr_bucket *e;
+        unsigned int activity;
+        int empty = APR_BRIGADE_EMPTY(bb);
+        apr_status_t status;
+
+        /*
+         * Mark that we have passed this way.
+         */
+        next->c->activity++;
+        activity = next->c->activity;
+
         if ((e = APR_BRIGADE_LAST(bb)) && APR_BUCKET_IS_EOS(e) && next->r) {
             /* This is only safe because HTTP_HEADER filter is always in
              * the filter stack.   This ensures that there is ALWAYS a
@@ -587,7 +597,25 @@
                 }
             }
         }
-        return next->frec->filter_func.out_func(next, bb);
+        status = next->frec->filter_func.out_func(next, bb);
+
+        /* No problems found, and we were we sent an empty brigade, and
+         * did this empty brigade not get passed on by a filter to the next
+         * filter in the chain? Compensate by passing the empty brigade to
+         * the next filter, so every filter gets a turn to write. This
+         * occurs during write completion.
+         */
+        while (APR_SUCCESS == status && empty) {
+            next = next->next;
+            if (next && next->c->activity == activity) {
+                status = next->frec->filter_func.out_func(next, bb);
+            }
+            else {
+                break;
+            }
+        }
+
+        return status;
     }
     return AP_NOBODY_WROTE;
 }
