You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@perl.apache.org by barries <ba...@slaysys.com> on 2001/05/22 17:33:58 UTC

[PATCH] add modperl_output_filter_send_EOS()

The current output filters implementation sends an EOS before the Perl
handler exists, cutting off trailing output from a filter like:

   sub handler {
       $f = shift ;
       $c = 0 ;
       while ( $f->read( my $buffer ) ) {
	   $c += length $buffer ;
	   $r->print( $buffer ) ;
       }
       $r->print( "$c bytes sent\n" ) ;
   }

This patch delays sending an EOS until the filter sub returns.

- Barrie

--- ./src/modules/perl/modperl_filter.c.orig	Wed May 16 16:28:19 2001
+++ ./src/modules/perl/modperl_filter.c	Tue May 22 10:52:49 2001
@@ -298,11 +298,6 @@
     }
 #endif
 
-    if (filter->eos && (len == 0)) {
-        /* if len > 0 then $filter->write will flush */
-        modperl_output_filter_flush(filter);
-    }
-
     return len;
 }
 
@@ -313,13 +308,26 @@
         return filter->rc;
     }
 
-    if (filter->eos) {
-        MP_TRACE_f(MP_FUNC, "sending EOS bucket\n");
-        filter->rc = send_eos(filter->f);
-        apr_brigade_destroy(filter->bb);
-        filter->bb = NULL;
-        filter->eos = 0;
+    return filter->rc;
+}
+
+MP_INLINE apr_status_t modperl_output_filter_send_EOS(modperl_filter_t *filter)
+{
+
+    filter->rc = modperl_output_filter_flush(filter);
+    if (filter->rc != APR_SUCCESS) {
+        return filter->rc;
+    }
+
+    if (!filter->eos) {
+        MP_TRACE_f(MP_FUNC, "WARNING: filter not at EOS bucket\n");
+        /* XXX Should we disgard remaining input? */
     }
+    MP_TRACE_f(MP_FUNC, "sending EOS bucket\n");
+    filter->rc = send_eos(filter->f);
+    apr_brigade_destroy(filter->bb);
+    filter->bb = NULL;
+    filter->eos = 0;
 
     return filter->rc;
 }
@@ -348,6 +356,7 @@
     else {
         filter = modperl_filter_new(f, bb, MP_OUTPUT_FILTER_MODE);
         status = modperl_run_filter(filter, 0, 0);
+        modperl_output_filter_send_EOS(filter);
     }
 
     switch (status) {
--- ./src/modules/perl/modperl_filter.h.orig	Tue May 22 11:07:06 2001
+++ ./src/modules/perl/modperl_filter.h	Tue May 22 11:07:28 2001
@@ -35,6 +35,7 @@
 void modperl_output_filter_register(request_rec *r);
 
 MP_INLINE apr_status_t modperl_output_filter_flush(modperl_filter_t *filter);
+MP_INLINE apr_status_t modperl_output_filter_send_EOS(modperl_filter_t *filter);
 
 MP_INLINE apr_ssize_t modperl_output_filter_read(pTHX_
                                                  modperl_filter_t *filter,
--- ./xs/Apache/Filter/Apache__Filter.h.orig	Tue May 22 10:54:12 2001
+++ ./xs/Apache/Filter/Apache__Filter.h	Tue May 22 11:05:24 2001
@@ -21,7 +21,7 @@
 
     if (modperl_filter->mode == MP_OUTPUT_FILTER_MODE) {
         mpxs_write_loop(modperl_output_filter_write, modperl_filter);
-        modperl_output_filter_flush(modperl_filter);
+        modperl_output_filter_send_EOS(modperl_filter);
     }
     else {
         croak("input filters not yet supported");

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org


Re: [PATCH] add modperl_output_filter_send_EOS()

Posted by barries <ba...@slaysys.com>.
On Tue, May 22, 2001 at 03:14:35PM -0700, Doug MacEachern wrote:
> i read on new-httpd that we do not need to send a eos bucket at all and
> apache will do the right thing.

I think Ryan is means that's true only for response handlers.
ap_finalize_request_protocol() sends an EOS if one hasn't been sent.
It's still incumbent on filters to pass them along, there's no
"finalization" or cleanup of the filter stack, it all just gets
vaporized by pool cleanup.

> interested in experimenting with that?  thanks!

Commenting out the call to send_eos() in my patched version definitely
causes loss of trailing data.

Though I did catch a bug whereby filter->bb is NULL (presumably due to
cleanup in get_bucket(). New patch below, which shouldn't send
extraneous EOSs.

If Perl code will eventually be able to do a
$filter->send_EOS(), modperl_filter_t will probably need an
"eos_sent" flag so we never send two EOSs.

- Barrie

--- ./src/modules/perl/modperl_filter.c.orig	Wed May 16 16:28:19 2001
+++ ./src/modules/perl/modperl_filter.c	Wed May 23 13:14:20 2001
@@ -298,11 +298,6 @@
     }
 #endif
 
-    if (filter->eos && (len == 0)) {
-        /* if len > 0 then $filter->write will flush */
-        modperl_output_filter_flush(filter);
-    }
-
     return len;
 }
 
@@ -313,13 +308,29 @@
         return filter->rc;
     }
 
+    return filter->rc;
+}
+
+MP_INLINE apr_status_t modperl_output_filter_send_EOS(modperl_filter_t *filter)
+{
+
+    filter->rc = modperl_output_filter_flush(filter);
+    if (filter->rc != APR_SUCCESS) {
+        return filter->rc;
+    }
+
     if (filter->eos) {
         MP_TRACE_f(MP_FUNC, "sending EOS bucket\n");
         filter->rc = send_eos(filter->f);
-        apr_brigade_destroy(filter->bb);
-        filter->bb = NULL;
-        filter->eos = 0;
+        if (filter->bb) {
+            apr_brigade_destroy(filter->bb);
+            filter->bb = NULL;
+        }
     }
+    filter->eos = 0;
+    /* XXX: do we need to protect against wierd events like two EOSs
+       coming down the pike? Or perl code sending an EOS and not
+       wanting to send a second EOS? */
 
     return filter->rc;
 }
@@ -348,6 +359,7 @@
     else {
         filter = modperl_filter_new(f, bb, MP_OUTPUT_FILTER_MODE);
         status = modperl_run_filter(filter, 0, 0);
+        modperl_output_filter_send_EOS(filter);
     }
 
     switch (status) {
--- ./src/modules/perl/modperl_filter.h.orig	Tue May 22 11:07:06 2001
+++ ./src/modules/perl/modperl_filter.h	Tue May 22 11:07:28 2001
@@ -35,6 +35,7 @@
 void modperl_output_filter_register(request_rec *r);
 
 MP_INLINE apr_status_t modperl_output_filter_flush(modperl_filter_t *filter);
+MP_INLINE apr_status_t modperl_output_filter_send_EOS(modperl_filter_t *filter);
 
 MP_INLINE apr_ssize_t modperl_output_filter_read(pTHX_
                                                  modperl_filter_t *filter,
--- ./xs/Apache/Filter/Apache__Filter.h.orig	Tue May 22 10:54:12 2001
+++ ./xs/Apache/Filter/Apache__Filter.h	Tue May 22 11:05:24 2001
@@ -21,7 +21,7 @@
 
     if (modperl_filter->mode == MP_OUTPUT_FILTER_MODE) {
         mpxs_write_loop(modperl_output_filter_write, modperl_filter);
-        modperl_output_filter_flush(modperl_filter);
+        modperl_output_filter_send_EOS(modperl_filter);
     }
     else {
         croak("input filters not yet supported");

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org


Re: [PATCH] add modperl_output_filter_send_EOS()

Posted by Doug MacEachern <do...@covalent.net>.
i read on new-httpd that we do not need to send a eos bucket at all and
apache will do the right thing.  interested in experimenting with
that?  thanks!



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org


Re: [PATCH] add modperl_output_filter_send_EOS()

Posted by barries <ba...@slaysys.com>.
On Tue, May 22, 2001 at 11:33:58AM -0400, barries wrote:
> The current output filters implementation sends an EOS before the Perl
> handler exists, cutting off trailing output from a filter like:

s/exists/exits/.  Anyway, this is probably a broken patch, since it
assumes the first bucket brigade has an EOS attached.

- Barrie

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org