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>