Geoffrey Young wrote:
hi all

I'm starting to work on this again (for the complete thread, in case it's not fresh in your mind, see http://marc.theaimsgroup.com/?t=105431745200001&r=1&w=2)

anyway, I'm working through an implementation that uses modperl_hook_t. as I'm going through it, the patch is getting bigger and bigger

ok, the changes required for this route were massive, and after spending a few days on it, it just didn't work out.


so, I'm back to my original plan. remembering from the past thread that this implementation

http://marc.theaimsgroup.com/?l=apache-modperl-dev&m=105431735200617&w=2

was preferred over this one

http://marc.theaimsgroup.com/?l=apache-modperl-dev&m=105458568726732&w=2

here is a new patch.

the only issue outstanding is with filter and ignoring the return status:

http://marc.theaimsgroup.com/?l=apache-modperl-dev&m=105462573626731&w=2

I think I'm of the opinion that we should keep the current behavior (respecting return values for filters) until assert() works properly. in either case, I'd like to patch that separately to reduce all-at-once changes - this code works for everything that calls modperl_callback_run_handlers, which is everything except filters.

oh, and the docs list PerlChildExitHandler as being of type RUN_ALL when actually it's coded as a VOID (the status is never checked) so I'll fix the docs there too once this is over.

--Geoff
Index: lib/ModPerl/Code.pm
===================================================================
RCS file: /home/cvspublic/modperl-2.0/lib/ModPerl/Code.pm,v
retrieving revision 1.100
diff -u -r1.100 Code.pm
--- lib/ModPerl/Code.pm 20 May 2003 01:31:49 -0000      1.100
+++ lib/ModPerl/Code.pm 7 Aug 2003 17:11:09 -0000
@@ -37,27 +37,32 @@
     Process    => {
         ret  => 'void',
         args => [{type => 'apr_pool_t', name => 'p'},
-                 {type => 'server_rec', name => 's'}],
+                 {type => 'server_rec', name => 's'},
+                 {type => 'dummy', name => 'VOID'}],
     },
     Files      => {
         ret  => 'int',
         args => [{type => 'apr_pool_t', name => 'pconf'},
                  {type => 'apr_pool_t', name => 'plog'},
                  {type => 'apr_pool_t', name => 'ptemp'},
-                 {type => 'server_rec', name => 's'}],
+                 {type => 'server_rec', name => 's'},
+                 {type => 'dummy', name => 'RUN_ALL'}],
     },
     PerSrv     => {
         ret  => 'int',
-        args => [{type => 'request_rec', name => 'r'}],
+        args => [{type => 'request_rec', name => 'r'}, 
+                 {type => 'dummy', name => 'RUN_ALL'}],
     },
     Connection => {
         ret  => 'int',
-        args => [{type => 'conn_rec', name => 'c'}],
+        args => [{type => 'conn_rec', name => 'c'},
+                 {type => 'dummy', name => 'RUN_FIRST'}],
     },
     PreConnection => {
         ret  => 'int',
         args => [{type => 'conn_rec', name => 'c'},
-                 {type => 'void', name => 'csd'}],
+                 {type => 'void', name => 'csd'},
+                 {type => 'dummy', name => 'RUN_ALL'}],
     },
 );
 
@@ -211,6 +216,12 @@
             my($protostr, $pass) = canon_proto($prototype, $name);
             my $ix = $self->{handler_index}->{$class}->[$i];
 
+            if ($callback =~ m/modperl_callback_per_(dir|srv)/) {
+                if ($ix =~ m/AUTH|TYPE|TRANS/) {
+                    $pass =~ s/RUN_ALL/RUN_FIRST/;
+                }
+            }
+
             print $h_fh "\n$protostr;\n";
 
             print $c_fh <<EOF;
@@ -557,8 +568,12 @@
 
 sub canon_args {
     my $args = shift->{args};
-    my @in   = map { "$_->{type} *$_->{name}" } @$args;
     my @pass = map { $_->{name} } @$args;
+    my @in;
+    foreach my $href (@$args) {
+      push @in, "$href->{type} *$href->{name}"
+        unless $href->{type} eq 'dummy';
+    }
     return wantarray ? ([EMAIL PROTECTED], [EMAIL PROTECTED]) : [EMAIL PROTECTED];
 }
 
Index: src/modules/perl/mod_perl.c
===================================================================
RCS file: /home/cvspublic/modperl-2.0/src/modules/perl/mod_perl.c,v
retrieving revision 1.175
diff -u -r1.175 mod_perl.c
--- src/modules/perl/mod_perl.c 6 Aug 2003 06:46:35 -0000       1.175
+++ src/modules/perl/mod_perl.c 7 Aug 2003 17:11:10 -0000
@@ -660,7 +660,7 @@
     char *level = NULL;
     server_rec *s = (server_rec *)data;
     
-    modperl_callback_process(MP_CHILD_EXIT_HANDLER, server_pool, s);
+    modperl_callback_process(MP_CHILD_EXIT_HANDLER, server_pool, s, VOID);
     
     if ((level = getenv("PERL_DESTRUCT_LEVEL"))) {
         modperl_destruct_level = atoi(level);
@@ -849,7 +849,7 @@
 
     modperl_response_init(r);
 
-    retval = modperl_callback_per_dir(MP_RESPONSE_HANDLER, r);
+    retval = modperl_callback_per_dir(MP_RESPONSE_HANDLER, r, RUN_FIRST);
 
     if ((retval == DECLINED) && r->content_type) {
         r->handler = r->content_type; /* let http_core or whatever try */
Index: src/modules/perl/modperl_callback.c
===================================================================
RCS file: /home/cvspublic/modperl-2.0/src/modules/perl/modperl_callback.c,v
retrieving revision 1.54
diff -u -r1.54 modperl_callback.c
--- src/modules/perl/modperl_callback.c 17 Feb 2003 09:03:16 -0000      1.54
+++ src/modules/perl/modperl_callback.c 7 Aug 2003 17:11:11 -0000
@@ -81,7 +81,8 @@
                                   request_rec *r, conn_rec *c, server_rec *s,
                                   apr_pool_t *pconf,
                                   apr_pool_t *plog,
-                                  apr_pool_t *ptemp)
+                                  apr_pool_t *ptemp,
+                                  modperl_hook_run_mode_e run_mode)
 {
 #ifdef USE_ITHREADS
     pTHX;
@@ -188,17 +189,61 @@
         
         MP_TRACE_h(MP_FUNC, "%s returned %d\n", handlers[i]->name, status);
 
-        if ((status != OK) && (status != DECLINED)) {
-            status = modperl_errsv(aTHX_ status, r, s);
+        /* follow Apache's lead and let OK terminate the phase for
+         * RUN_FIRST handlers.  RUN_ALL handlers keep going on OK.
+         * VOID handler ignore all errors.
+         */
+
+        if (run_mode == RUN_ALL) {
+            /* the normal case:
+             *   OK and DECLINED continue 
+             *   errors end the phase
+             */
+            if ((status != OK) && (status != DECLINED)) {
+
+                status = modperl_errsv(aTHX_ status, r, s);
 #ifdef MP_TRACE
-            if (i+1 != nelts) {
-                MP_TRACE_h(MP_FUNC, "there were %d uncalled handlers\n",
-                           nelts-i-1);
-            }
+                if (i+1 != nelts) {
+                    MP_TRACE_h(MP_FUNC, "error status %d leaves %d uncalled 
handlers\n",
+                               status, desc, nelts-i-1);
+                }
 #endif
-            break;
+                break;
+            }
         }
+        else if (run_mode == RUN_FIRST) {
+            /* the exceptional case:
+             *   OK and errors end the phase
+             *   DECLINED continues
+             */
 
+            if (status == OK) {
+#ifdef MP_TRACE
+                if (i+1 != nelts) {
+                    MP_TRACE_h(MP_FUNC, "OK ends the %s stack, leaving %d uncalled 
handlers\n",
+                               desc, nelts-i-1);
+                }
+#endif
+                break;
+            }
+            if (status != DECLINED) {
+                status = modperl_errsv(aTHX_ status, r, s);
+#ifdef MP_TRACE
+                if (i+1 != nelts) {
+                    MP_TRACE_h(MP_FUNC, "error status %d leaves %d uncalled 
handlers\n",
+                               status, desc, nelts-i-1);
+                }
+#endif
+                break;
+            }
+        }
+        else {
+            /* the rare case.
+             * VOID handlers completely ignore the return status
+             * Apache should handle whatever mod_perl returns, 
+             * so there is no need to mess with the status
+             */
+        }
     }
 
     SvREFCNT_dec((SV*)av_args);
@@ -213,46 +258,52 @@
     return status;
 }
 
-int modperl_callback_per_dir(int idx, request_rec *r)
+int modperl_callback_per_dir(int idx, request_rec *r,
+                             modperl_hook_run_mode_e run_mode)
 {
     return modperl_callback_run_handlers(idx, MP_HANDLER_TYPE_PER_DIR,
                                          r, NULL, r->server,
-                                         NULL, NULL, NULL);
+                                         NULL, NULL, NULL, run_mode);
 }
 
-int modperl_callback_per_srv(int idx, request_rec *r)
+int modperl_callback_per_srv(int idx, request_rec *r, 
+                             modperl_hook_run_mode_e run_mode)
 {
     return modperl_callback_run_handlers(idx, MP_HANDLER_TYPE_PER_SRV,
                                          r, NULL, r->server,
-                                         NULL, NULL, NULL);
+                                         NULL, NULL, NULL, run_mode);
 }
 
-int modperl_callback_connection(int idx, conn_rec *c)
+int modperl_callback_connection(int idx, conn_rec *c, 
+                                modperl_hook_run_mode_e run_mode)
 {
     return modperl_callback_run_handlers(idx, MP_HANDLER_TYPE_CONNECTION,
                                          NULL, c, c->base_server,
-                                         NULL, NULL, NULL);
+                                         NULL, NULL, NULL, run_mode);
 }
 
-int modperl_callback_pre_connection(int idx, conn_rec *c, void *csd)
+int modperl_callback_pre_connection(int idx, conn_rec *c, void *csd,
+                                    modperl_hook_run_mode_e run_mode)
 {
     return modperl_callback_run_handlers(idx, MP_HANDLER_TYPE_PRE_CONNECTION,
                                          NULL, c, c->base_server,
-                                         NULL, NULL, NULL);
+                                         NULL, NULL, NULL, run_mode);
 }
 
-void modperl_callback_process(int idx, apr_pool_t *p, server_rec *s)
+void modperl_callback_process(int idx, apr_pool_t *p, server_rec *s,
+                              modperl_hook_run_mode_e run_mode)
 {
     modperl_callback_run_handlers(idx, MP_HANDLER_TYPE_PROCESS,
                                   NULL, NULL, s,
-                                  p, NULL, NULL);
+                                  p, NULL, NULL, run_mode);
 }
 
 int modperl_callback_files(int idx,
                            apr_pool_t *pconf, apr_pool_t *plog,
-                           apr_pool_t *ptemp, server_rec *s)
+                           apr_pool_t *ptemp, server_rec *s,
+                           modperl_hook_run_mode_e run_mode)
 {
     return modperl_callback_run_handlers(idx, MP_HANDLER_TYPE_FILES,
                                          NULL, NULL, s,
-                                         pconf, plog, ptemp);
+                                         pconf, plog, ptemp, run_mode);
 }
Index: src/modules/perl/modperl_callback.h
===================================================================
RCS file: /home/cvspublic/modperl-2.0/src/modules/perl/modperl_callback.h,v
retrieving revision 1.22
diff -u -r1.22 modperl_callback.h
--- src/modules/perl/modperl_callback.h 17 Feb 2003 09:03:16 -0000      1.22
+++ src/modules/perl/modperl_callback.h 7 Aug 2003 17:11:11 -0000
@@ -26,20 +26,27 @@
                                   request_rec *r, conn_rec *c, server_rec *s,
                                   apr_pool_t *pconf,
                                   apr_pool_t *plog,
-                                  apr_pool_t *ptemp);
+                                  apr_pool_t *ptemp,
+                                  modperl_hook_run_mode_e run_mode);
 
-int modperl_callback_per_dir(int idx, request_rec *r);
+int modperl_callback_per_dir(int idx, request_rec *r, 
+                             modperl_hook_run_mode_e run_mode);
 
-int modperl_callback_per_srv(int idx, request_rec *r);
+int modperl_callback_per_srv(int idx, request_rec *r,
+                             modperl_hook_run_mode_e run_mode);
 
-int modperl_callback_connection(int idx, conn_rec *c);
+int modperl_callback_connection(int idx, conn_rec *c,
+                                modperl_hook_run_mode_e run_mode);
 
-int modperl_callback_pre_connection(int idx, conn_rec *c, void *csd);
+int modperl_callback_pre_connection(int idx, conn_rec *c, void *csd,
+                                    modperl_hook_run_mode_e run_mode);
 
-void modperl_callback_process(int idx, apr_pool_t *p, server_rec *s);
+void modperl_callback_process(int idx, apr_pool_t *p, server_rec *s,
+                              modperl_hook_run_mode_e run_mode);
 
 int modperl_callback_files(int idx,
                            apr_pool_t *pconf, apr_pool_t *plog,
-                           apr_pool_t *ptemp, server_rec *s);
+                           apr_pool_t *ptemp, server_rec *s,
+                           modperl_hook_run_mode_e run_mode);
 
 #endif /* MODPERL_CALLBACK_H */
Index: src/modules/perl/modperl_config.c
===================================================================
RCS file: /home/cvspublic/modperl-2.0/src/modules/perl/modperl_config.c,v
retrieving revision 1.63
diff -u -r1.63 modperl_config.c
--- src/modules/perl/modperl_config.c   20 May 2003 06:02:47 -0000      1.63
+++ src/modules/perl/modperl_config.c   7 Aug 2003 17:11:11 -0000
@@ -290,7 +290,7 @@
         rcfg->pnotes = Nullhv;
     }
 
-    retval = modperl_callback_per_dir(MP_CLEANUP_HANDLER, r);
+    retval = modperl_callback_per_dir(MP_CLEANUP_HANDLER, r, RUN_ALL);
     
     return retval;
 }
Index: src/modules/perl/modperl_filter.c
===================================================================
RCS file: /home/cvspublic/modperl-2.0/src/modules/perl/modperl_filter.c,v
retrieving revision 1.64
diff -u -r1.64 modperl_filter.c
--- src/modules/perl/modperl_filter.c   13 May 2003 09:18:58 -0000      1.64
+++ src/modules/perl/modperl_filter.c   7 Aug 2003 17:11:14 -0000
@@ -341,6 +341,7 @@
     modperl_filter_mg_set(aTHX_ AvARRAY(args)[0],
                           modperl_filter_new(f, NULL, mode, 0, 0, 0));
 
+    /* filters are VOID handlers.  should we ignore the status? */
     if ((status = modperl_callback(aTHX_ handler, p, r, s, args)) != OK) {
         status = modperl_errsv(aTHX_ status, r, s);
     }
@@ -384,6 +385,7 @@
         av_push(args, newSViv(filter->readbytes));
     }
 
+    /* filters are VOID handlers.  should we ignore the status? */
     if ((status = modperl_callback(aTHX_ handler, p, r, s, args)) != OK) {
         status = modperl_errsv(aTHX_ status, r, s);
     }
Index: src/modules/perl/modperl_types.h
===================================================================
RCS file: /home/cvspublic/modperl-2.0/src/modules/perl/modperl_types.h,v
retrieving revision 1.67
diff -u -r1.67 modperl_types.h
--- src/modules/perl/modperl_types.h    30 May 2003 12:55:14 -0000      1.67
+++ src/modules/perl/modperl_types.h    7 Aug 2003 17:11:17 -0000
@@ -248,4 +248,10 @@
     const char *func_name;
 } modperl_module_cmd_data_t;
 
+typedef enum {
+    RUN_ALL,
+    RUN_FIRST,
+    VOID
+} modperl_hook_run_mode_e;
+
 #endif /* MODPERL_TYPES_H */
Index: src/modules/perl/modperl_util.h
===================================================================
RCS file: /home/cvspublic/modperl-2.0/src/modules/perl/modperl_util.h,v
retrieving revision 1.42
diff -u -r1.42 modperl_util.h
--- src/modules/perl/modperl_util.h     14 Mar 2003 05:50:31 -0000      1.42
+++ src/modules/perl/modperl_util.h     7 Aug 2003 17:11:17 -0000
@@ -64,7 +64,7 @@
     }
 
 /* turn off cgi header parsing. in case we are already inside
- *     modperl_callback_per_dir(MP_RESPONSE_HANDLER, r); 
+ *     modperl_callback_per_dir(MP_RESPONSE_HANDLER, r, RUN_FIRST); 
  * but haven't sent any data yet, it's too late to change
  * MpReqPARSE_HEADERS, so change the wbucket's private flag directly
  */
Index: t/hooks/TestHooks/init.pm
===================================================================
RCS file: /home/cvspublic/modperl-2.0/t/hooks/TestHooks/init.pm,v
retrieving revision 1.4
diff -u -r1.4 init.pm
--- t/hooks/TestHooks/init.pm   31 Mar 2003 01:50:52 -0000      1.4
+++ t/hooks/TestHooks/init.pm   7 Aug 2003 17:11:17 -0000
@@ -8,7 +8,7 @@
 use APR::Table ();
 use Apache::RequestRec ();
 
-use Apache::Const -compile => 'OK';
+use Apache::Const -compile => qw(OK DECLINED);
 
 sub first {
     my $r = shift;
@@ -35,7 +35,7 @@
 
     $r->notes->set(ok3 => $ok + 1);
 
-    Apache::OK;
+    Apache::DECLINED;
 }
 
 sub response {
Index: t/hooks/TestHooks/push_handlers.pm
===================================================================
RCS file: /home/cvspublic/modperl-2.0/t/hooks/TestHooks/push_handlers.pm,v
retrieving revision 1.5
diff -u -r1.5 push_handlers.pm
--- t/hooks/TestHooks/push_handlers.pm  18 Apr 2003 06:18:57 -0000      1.5
+++ t/hooks/TestHooks/push_handlers.pm  7 Aug 2003 17:11:17 -0000
@@ -39,7 +39,7 @@
 }
 
 sub end { return Apache::DONE }
-sub say { shift->print(shift,"\n"); return Apache::OK }
+sub say { shift->print(shift,"\n"); return Apache::DECLINED }
 
 sub conf {
     # this one is configured from httpd.conf
Index: t/hooks/TestHooks/stacked_handlers.pm
===================================================================
RCS file: /home/cvspublic/modperl-2.0/t/hooks/TestHooks/stacked_handlers.pm,v
retrieving revision 1.5
diff -u -r1.5 stacked_handlers.pm
--- t/hooks/TestHooks/stacked_handlers.pm       18 Apr 2003 06:18:57 -0000      1.5
+++ t/hooks/TestHooks/stacked_handlers.pm       7 Aug 2003 17:11:17 -0000
@@ -28,7 +28,7 @@
     $r->content_type('text/plain');
     $r->print("one\n");
 
-    return Apache::OK;
+    return Apache::DECLINED;
 }
 
 sub two {
@@ -36,7 +36,7 @@
 
     $r->print("two\n");
 
-    return Apache::OK;
+    return Apache::DECLINED;
 }
 
 sub three {
Index: xs/tables/current/ModPerl/FunctionTable.pm
===================================================================
RCS file: /home/cvspublic/modperl-2.0/xs/tables/current/ModPerl/FunctionTable.pm,v
retrieving revision 1.117
diff -u -r1.117 FunctionTable.pm
--- xs/tables/current/ModPerl/FunctionTable.pm  7 Jul 2003 03:06:14 -0000       1.117
+++ xs/tables/current/ModPerl/FunctionTable.pm  7 Aug 2003 17:11:21 -0000
@@ -150,6 +150,10 @@
       {
         'type' => 'conn_rec *',
         'name' => 'c'
+      },
+      {
+        'type' => 'modperl_hook_run_mode_e',
+        'name' => 'run_mode'
       }
     ]
   },
@@ -176,6 +180,10 @@
       {
         'type' => 'server_rec *',
         'name' => 's'
+      },
+      {
+        'type' => 'modperl_hook_run_mode_e',
+        'name' => 'run_mode'
       }
     ]
   },
@@ -190,6 +198,10 @@
       {
         'type' => 'request_rec *',
         'name' => 'r'
+      },
+      {
+        'type' => 'modperl_hook_run_mode_e',
+        'name' => 'run_mode'
       }
     ]
   },
@@ -204,6 +216,10 @@
       {
         'type' => 'request_rec *',
         'name' => 'r'
+      },
+      {
+        'type' => 'modperl_hook_run_mode_e',
+        'name' => 'run_mode'
       }
     ]
   },
@@ -222,6 +238,10 @@
       {
         'type' => 'void *',
         'name' => 'csd'
+      },
+      {
+        'type' => 'modperl_hook_run_mode_e',
+        'name' => 'run_mode'
       }
     ]
   },
@@ -240,6 +260,10 @@
       {
         'type' => 'server_rec *',
         'name' => 's'
+      },
+      {
+        'type' => 'modperl_hook_run_mode_e',
+        'name' => 'run_mode'
       }
     ]
   },
@@ -278,6 +302,10 @@
       {
         'type' => 'apr_pool_t *',
         'name' => 'ptemp'
+      },
+      {
+        'type' => 'modperl_hook_run_mode_e',
+        'name' => 'run_mode'
       }
     ]
   },

--- /dev/null   2003-01-30 05:24:37.000000000 -0500
+++ t/hooks/stacked_handlers2.t 2003-08-06 15:40:34.000000000 -0400
@@ -0,0 +1,34 @@
+use strict;
+use warnings FATAL => 'all';
+
+use Apache::TestRequest;
+use Apache::Test;
+use Apache::TestUtil;
+
+my $module   = "TestHooks::stacked_handlers2";
+Apache::TestRequest::module($module);
+
+my $config   = Apache::Test::config();
+my $hostport = Apache::TestRequest::hostport($config);
+my $path     = Apache::TestRequest::module2path($module);
+
+my $location = "http://$hostport/$path";;
+
+t_debug("connecting to $location");
+
+plan tests => 1;
+
+my $expected = q!ran 2 PerlPostReadRequestHandler handlers
+ran 1 PerlTransHandler handlers
+ran 4 PerlHeaderParserHandler handlers
+ran 2 PerlAccessHandler handlers
+ran 2 PerlAuthenHandler handlers
+ran 2 PerlAuthzHandler handlers
+ran 1 PerlTypeHandler handlers
+ran 2 PerlFixupHandler handlers
+ran 2 PerlResponseHandler handlers
+ran 2 PerlOutputFilterHandler handlers!;
+
+chomp(my $received = GET_BODY_ASSERT $location);
+
+ok t_cmp($expected, $received, "stacked_handlers");

--- /dev/null   2003-01-30 05:24:37.000000000 -0500
+++ t/hooks/TestHooks/stacked_handlers2.pm      2003-08-07 12:57:11.000000000 -0400
@@ -0,0 +1,179 @@
+package TestHooks::stacked_handlers2;
+
+# this test exercises the execution of the stacked handlers 
+# connection, translation, authen, authz, type, and response
+# phases should end for the first handler that returns OK
+
+use strict;
+use warnings FATAL => 'all';
+
+use Apache::RequestRec ();
+use Apache::RequestIO ();
+use Apache::Filter ();
+
+use APR::Table;
+
+use Apache::Const -compile => qw(OK DECLINED AUTH_REQUIRED SERVER_ERROR);
+
+sub ok { 
+
+  callback(shift);
+
+  return Apache::OK 
+}
+
+sub declined { 
+
+  callback(shift);
+
+  return Apache::DECLINED
+}
+
+sub auth_required { 
+
+  callback(shift);
+
+  return Apache::AUTH_REQUIRED
+}
+
+sub server_error { 
+
+  callback(shift);
+
+  return Apache::SERVER_ERROR
+}
+
+sub callback {
+
+  my $obj = shift;
+
+  my ($r, $callback);
+
+  if ($obj->isa('Apache::Filter')) {
+    $r = $obj->r;
+    $callback = 'PerlOutputFilterHandler';
+  }
+  else {
+    $r = $obj
+  }
+
+  $callback ||= Apache::current_callback;
+
+  my $count = $r->notes->get($callback) || 0;
+
+  $r->notes->set($callback, ++$count);
+}
+
+sub handler {
+
+    my $r = shift;
+
+    $r->content_type('text/plain');
+
+    callback($r);
+
+    foreach my $callback (qw(PerlPostReadRequestHandler
+                             PerlTransHandler
+                             PerlHeaderParserHandler 
+                             PerlAccessHandler 
+                             PerlAuthenHandler 
+                             PerlAuthzHandler
+                             PerlTypeHandler
+                             PerlFixupHandler
+                             PerlResponseHandler)) {
+
+        my $count = $r->notes->get($callback) || 0;
+ 
+        $r->print("ran $count $callback handlers\n");
+    }
+
+    return Apache::OK;
+}
+
+sub passthru {
+    my $filter = shift;
+
+    unless ($filter->ctx) {
+       callback($filter);
+       $filter->ctx({seen => 1});
+    }
+
+    while ($filter->read(my $buffer, 1024)) {
+        $filter->print($buffer);
+    }
+
+    # this should be ignored?
+    Apache::OK;
+}
+
+sub filter {
+    my $filter = shift;
+
+    unless ($filter->ctx) {
+        callback($filter);
+        $filter->ctx({seen => 1});
+    }
+
+    while ($filter->read(my $buffer, 1024)) {
+        $filter->print($buffer);
+    }
+
+    if ($filter->seen_eos) {
+        my $count = $filter->r->notes->get('PerlOutputFilterHandler') || 0;
+
+        $filter->print("ran $count PerlOutputFilterHandler handlers\n");
+    }
+
+    # this should be ignored?
+    Apache::OK;
+}
+
+1;
+__DATA__
+# create a new virtual host so we can test (almost all) all the hooks
+<NoAutoConfig>
+<VirtualHost TestHooks::stacked_handlers2>
+
+  PerlModule TestHooks::stacked_handlers2
+
+  # all 2 run
+  PerlPostReadRequestHandler TestHooks::stacked_handlers2::ok 
TestHooks::stacked_handlers2::ok
+
+  # 1 run, 1 left behind
+  PerlTransHandler TestHooks::stacked_handlers2::ok 
TestHooks::stacked_handlers2::server_error
+
+  <Location /TestHooks__stacked_handlers2>
+      # all 4 run
+      PerlHeaderParserHandler TestHooks::stacked_handlers2::ok 
TestHooks::stacked_handlers2::declined
+      PerlHeaderParserHandler TestHooks::stacked_handlers2::declined 
TestHooks::stacked_handlers2::ok
+
+      # all 2 run
+      PerlAccessHandler TestHooks::stacked_handlers2::ok 
TestHooks::stacked_handlers2::ok 
+
+      # 2 run, 1 left behind
+      PerlAuthenHandler TestHooks::stacked_handlers2::declined 
TestHooks::stacked_handlers2::ok 
+      PerlAuthenHandler TestHooks::stacked_handlers2::auth_required
+
+      # 2 run, 1 left behind
+      PerlAuthzHandler TestHooks::stacked_handlers2::declined 
TestHooks::stacked_handlers2::ok 
+      PerlAuthzHandler TestHooks::stacked_handlers2::auth_required
+
+      # 1 run, 1 left behind
+      PerlTypeHandler  TestHooks::stacked_handlers2::ok 
TestHooks::stacked_handlers3::server_error
+
+      # all 2 run
+      PerlFixupHandler TestHooks::stacked_handlers2::ok 
TestHooks::stacked_handlers2::ok
+
+      # 2 run, 2 left behind
+      PerlResponseHandler TestHooks::stacked_handlers2::declined 
TestHooks::stacked_handlers2 
+      PerlResponseHandler TestHooks::stacked_handlers2::ok 
TestHooks::stacked_handlers2::server_error
+
+      SetHandler modperl
+      AuthType Basic
+      Require valid-user
+
+      PerlOutputFilterHandler TestHooks::stacked_handlers2::passthru 
TestHooks::stacked_handlers2::filter
+  </Location>
+
+</VirtualHost>
+</NoAutoConfig>

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to