stas 2004/02/09 11:08:35
Modified: . Changes todo release src/modules/perl modperl_callback.c t/hooks .cvsignore Added: t/hooks/TestHooks push_handlers_same_phase.pm Removed: t/error push_handlers.t t/response/TestError push_handlers.pm Log: it's now possible to push new handlers into the same phase that is running at the moment + tests Revision Changes Path 1.323 +3 -0 modperl-2.0/Changes Index: Changes =================================================================== RCS file: /home/cvs/modperl-2.0/Changes,v retrieving revision 1.322 retrieving revision 1.323 diff -u -u -r1.322 -r1.323 --- Changes 9 Feb 2004 19:05:59 -0000 1.322 +++ Changes 9 Feb 2004 19:08:35 -0000 1.323 @@ -12,6 +12,9 @@ =item 1.99_13-dev +it's now possible to push new handlers into the same phase that is +running at the moment [Stas]. + when $r->handler($new_handler) is called from a response phase, it now checks that the response handler type is not switched (e.g. from 'modperl' to 'perl-script') from the currently used one [Stas] 1.12 +0 -4 modperl-2.0/todo/release Index: release =================================================================== RCS file: /home/cvs/modperl-2.0/todo/release,v retrieving revision 1.11 retrieving revision 1.12 diff -u -u -r1.11 -r1.12 --- release 9 Feb 2004 18:44:43 -0000 1.11 +++ release 9 Feb 2004 19:08:35 -0000 1.12 @@ -131,10 +131,6 @@ beginning of child_end it'll raise the flag and lower it at the end of child_exit. -* push_handlers has a problem when called to add handlers to the - current phase (segfaults, see t/error/push_handlers.t) check that - get_handlers sees that added handler. - * Apache::Reload - needs to handle properly redefined subs warnings 1.66 +27 -18 modperl-2.0/src/modules/perl/modperl_callback.c Index: modperl_callback.c =================================================================== RCS file: /home/cvs/modperl-2.0/src/modules/perl/modperl_callback.c,v retrieving revision 1.65 retrieving revision 1.66 diff -u -u -r1.65 -r1.66 --- modperl_callback.c 9 Jan 2004 04:59:18 -0000 1.65 +++ modperl_callback.c 9 Feb 2004 19:08:35 -0000 1.66 @@ -132,7 +132,7 @@ modperl_handler_t **handlers; apr_pool_t *p = NULL; MpAV *av, **avp; - int i, nelts, status = OK; + int i, status = OK; const char *desc = NULL; AV *av_args = Nullav; @@ -213,17 +213,11 @@ modperl_callback_current_callback_set(desc); - /* XXX: deal with {push,set}_handler of the phase we're currently in */ - /* for now avoid the segfault by not letting av->nelts grow if - * somebody push_handlers to the phase we are currently in, but - * different handler e.g. jumping from 'modperl' to 'perl-script', - * before calling push_handler */ - nelts = av->nelts; MP_TRACE_h(MP_FUNC, "[%s] running %d %s handlers\n", - modperl_pid_tid(p), nelts, desc); + modperl_pid_tid(p), av->nelts, desc); handlers = (modperl_handler_t **)av->elts; - for (i=0; i<nelts; i++) { + for (i=0; i<av->nelts; i++) { status = modperl_callback(aTHX_ handlers[i], p, r, s, av_args); MP_TRACE_h(MP_FUNC, "%s returned %d\n", handlers[i]->name, status); @@ -242,9 +236,10 @@ 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); + if (i+1 != av->nelts) { + MP_TRACE_h(MP_FUNC, "error status %d leaves %d " + "uncalled handlers\n", + status, desc, av->nelts-i-1); } #endif break; @@ -258,9 +253,10 @@ 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); + if (i+1 != av->nelts) { + MP_TRACE_h(MP_FUNC, "OK ends the %s stack, " + "leaving %d uncalled handlers\n", + desc, av->nelts-i-1); } #endif break; @@ -268,9 +264,10 @@ 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); + if (i+1 != av->nelts) { + MP_TRACE_h(MP_FUNC, "error status %d leaves %d " + "uncalled handlers\n", + status, desc, av->nelts-i-1); } #endif break; @@ -282,6 +279,18 @@ * Apache should handle whatever mod_perl returns, * so there is no need to mess with the status */ + } + + /* it's possible that during the last callback a new handler + * was pushed onto the same phase it's running from. av needs + * to be updated. + * + * XXX: would be nice to somehow optimize that + */ + avp = modperl_handler_lookup_handlers(dcfg, scfg, rcfg, p, + type, idx, FALSE, NULL); + if (avp && (av = *avp)) { + handlers = (modperl_handler_t **)av->elts; } } 1.4 +1 -0 modperl-2.0/t/hooks/.cvsignore Index: .cvsignore =================================================================== RCS file: /home/cvs/modperl-2.0/t/hooks/.cvsignore,v retrieving revision 1.3 retrieving revision 1.4 diff -u -u -r1.3 -r1.4 --- .cvsignore 6 Oct 2001 19:44:30 -0000 1.3 +++ .cvsignore 9 Feb 2004 19:08:35 -0000 1.4 @@ -5,3 +5,4 @@ fixup.t trans.t init.t +push_handlers_same_phase.t \ No newline at end of file 1.1 modperl-2.0/t/hooks/TestHooks/push_handlers_same_phase.pm Index: push_handlers_same_phase.pm =================================================================== package TestHooks::push_handlers_same_phase; # test that we # - can push handlers into the same phase that is currently running # - cannot switch 'perl-script' to 'modperl' and vice versa once # inside the response phase use strict; use warnings FATAL => 'all'; use Apache::RequestRec (); use Apache::RequestIO (); use Apache::RequestUtil (); use APR::Table (); use Apache::Test; use Apache::TestUtil; use Apache::Const -compile => qw(OK DECLINED); sub handler { my $r = shift; my $counter = $r->notes->get('counter') || 0; $r->notes->set(counter => $counter+1); $r->push_handlers(PerlResponseHandler => \&real_response); return Apache::DECLINED; } sub real_response { my $r = shift; plan $r, tests => 3; # test that we don't rerun all the handlers again (it should no # longer happen as we don't allow switching 'perl-script' <=> # 'modperl' on the go, but test anyway) my $counter = $r->notes->get('counter') || 0; ok t_cmp(1, $counter, __PACKAGE__ . "::handler must have been called only once"); my @handlers = @{ $r->get_handlers('PerlResponseHandler') || []}; ok t_cmp(2, scalar(@handlers), "there should be 2 response handlers"); # once running inside the response phase it shouldn't be possible # to switch from 'perl-script' to 'modperl' and vice versa eval { $r->handler("perl-script") }; ok t_cmp(qr/Can't switch from/, $@, "can't switch from 'perl-script' to 'modperl' inside " . "the response phase"); return Apache::OK; } 1; __END__ <NoAutoConfig> <Location /TestHooks__push_handlers_same_phase> SetHandler modperl PerlResponseHandler TestHooks::push_handlers_same_phase </Location> </NoAutoConfig>