Author: stas Date: Wed Nov 24 11:32:47 2004 New Revision: 106450 URL: http://svn.apache.org/viewcvs?view=rev&rev=106450 Log: replace the slow implementation of anon handlers using B::Deparse, with per-interpreter cache of compiled CODE refs (sort of emulating named subroutines for anonymous handlers)
Modified: perl/modperl/trunk/Changes perl/modperl/trunk/src/modules/perl/mod_perl.c perl/modperl/trunk/src/modules/perl/modperl_callback.c perl/modperl/trunk/src/modules/perl/modperl_handler.c perl/modperl/trunk/src/modules/perl/modperl_handler.h perl/modperl/trunk/src/modules/perl/modperl_mgv.c perl/modperl/trunk/src/modules/perl/modperl_perl_global.c perl/modperl/trunk/src/modules/perl/modperl_perl_global.h perl/modperl/trunk/src/modules/perl/modperl_types.h perl/modperl/trunk/src/modules/perl/modperl_util.c perl/modperl/trunk/src/modules/perl/modperl_util.h perl/modperl/trunk/t/filter/both_str_req_add.t perl/modperl/trunk/t/hooks/TestHooks/push_handlers_blessed.pm perl/modperl/trunk/t/hooks/push_handlers.t Modified: perl/modperl/trunk/Changes Url: http://svn.apache.org/viewcvs/perl/modperl/trunk/Changes?view=diff&rev=106450&p1=perl/modperl/trunk/Changes&r1=106449&p2=perl/modperl/trunk/Changes&r2=106450 ============================================================================== --- perl/modperl/trunk/Changes (original) +++ perl/modperl/trunk/Changes Wed Nov 24 11:32:47 2004 @@ -12,6 +12,10 @@ =item 1.99_18-dev +replace the slow implementation of anon handlers using B::Deparse, +with per-interpreter cache of compiled CODE refs (sort of emulating +named subroutines for anonymous handlers) [Stas]. + avoid segfaults when a bogus $r object is used [Stas] Remove magicness of PerlLoadModule and implement Apache::Module::add() Modified: perl/modperl/trunk/src/modules/perl/mod_perl.c Url: http://svn.apache.org/viewcvs/perl/modperl/trunk/src/modules/perl/mod_perl.c?view=diff&rev=106450&p1=perl/modperl/trunk/src/modules/perl/mod_perl.c&r1=106449&p2=perl/modperl/trunk/src/modules/perl/mod_perl.c&r2=106450 ============================================================================== --- perl/modperl/trunk/src/modules/perl/mod_perl.c (original) +++ perl/modperl/trunk/src/modules/perl/mod_perl.c Wed Nov 24 11:32:47 2004 @@ -280,6 +280,8 @@ newSVpv(ap_server_root_relative(p, "lib/perl"), 0)); #endif /* MP_COMPAT_1X */ + modperl_handler_anon_init(aTHX_ p); + if (!modperl_config_apply_PerlRequire(s, scfg, perl, p)) { exit(1); } Modified: perl/modperl/trunk/src/modules/perl/modperl_callback.c Url: http://svn.apache.org/viewcvs/perl/modperl/trunk/src/modules/perl/modperl_callback.c?view=diff&rev=106450&p1=perl/modperl/trunk/src/modules/perl/modperl_callback.c&r1=106449&p2=perl/modperl/trunk/src/modules/perl/modperl_callback.c&r2=106450 ============================================================================== --- perl/modperl/trunk/src/modules/perl/modperl_callback.c (original) +++ perl/modperl/trunk/src/modules/perl/modperl_callback.c Wed Nov 24 11:32:47 2004 @@ -67,20 +67,8 @@ if (MpHandlerANON(handler)) { #ifdef USE_ITHREADS - /* it's possible that the interpreter that is running the anon - * cv, isn't the one that compiled it. so to be safe need to - * re-eval the deparsed form before using it. - * XXX: possible optimizations, see modperl_handler_new_anon */ - SV *sv = eval_pv(handler->name, TRUE); - cv = (CV*)SvRV(sv); + cv = modperl_handler_anon_get(aTHX_ handler->mgv_obj); #else - /* the same interpreter that has compiled the anon cv is used - * to run it */ - if (!handler->cv) { - SV *sv = eval_pv(handler->name, TRUE); - handler->cv = (CV*)SvRV(sv); /* cache */ - SvREFCNT_inc(handler->cv); - } cv = handler->cv; #endif } @@ -90,7 +78,6 @@ cv = modperl_mgv_cv(gv); } else { - const char *name; modperl_mgv_t *symbol = handler->mgv_cv; Modified: perl/modperl/trunk/src/modules/perl/modperl_handler.c Url: http://svn.apache.org/viewcvs/perl/modperl/trunk/src/modules/perl/modperl_handler.c?view=diff&rev=106450&p1=perl/modperl/trunk/src/modules/perl/modperl_handler.c&r1=106449&p2=perl/modperl/trunk/src/modules/perl/modperl_handler.c&r2=106450 ============================================================================== --- perl/modperl/trunk/src/modules/perl/modperl_handler.c (original) +++ perl/modperl/trunk/src/modules/perl/modperl_handler.c Wed Nov 24 11:32:47 2004 @@ -43,6 +43,115 @@ return handler; } +/* How anon-subs are handled: + * We have two ways anon-subs can be registered + * A) at startup from httpd.conf: + * PerlTransHandler 'sub { ... }' + * B) run-time perl code + * $r->push_handlers(PerlTransHandler => sub { .... }); + * + * In the case of non-threaded perl, we just compile A or grab B and + * store it in the mod_perl struct and call it when it's used. No + * problems here + * + * In the case of threads, things get more complicated. we no longer + * can store the CV value of the compiled anon-sub, since when + * perl_clone is called each interpreter will have a different CV + * value. since we need to be able to have 1 entry for each anon-sub + * across all interpreters a different solution is needed. to remind + * in the case of named subs, we just store the name of the sub and + * look its corresponding CV when we need it. + * + * The used solution: each process has a global counter, which always + * grows. Every time a new anon-sub is encountered, a new ID is + * allocated from that process-global counter and that ID is stored in + * the mod_perl struct. The compiled CV is stored as + * $PL_modglobal{ANONSUB}{$id} = CV; + * when perl_clone is called, each clone will clone that CV value, but + * we will still be able to find it, since we stored it in the + * hash. so we retrieve the CV value, whatever it is and we run it. + * + * that explanation can be written and run in perl: + * + * use threads; + * our %h; + * $h{x} = eval 'sub { print qq[this is sub @_\n] }'; + * $h{x}->("main"); + * threads->new(sub { $h{x}->(threads->self->tid)}); + * + * XXX: more nuances will follow + */ + +void modperl_handler_anon_init(pTHX_ apr_pool_t *p) +{ + modperl_modglobal_key_t *gkey = + modperl_modglobal_lookup(aTHX_ "ANONSUB"); + MP_TRACE_h(MP_FUNC, "init $PL_modglobal{ANONSUB} = []"); + MP_MODGLOBAL_STORE_HV(gkey); + + /* init the counter to 0 */ + modperl_global_anon_cnt_init(p); +} + +/* allocate and populate the anon handler sub-struct */ +MP_INLINE modperl_mgv_t *modperl_handler_anon_next(pTHX_ apr_pool_t *p) +{ + /* re-use modperl_mgv_t entry which is otherwise is not used + * by anon handlers */ + modperl_mgv_t *anon = + (modperl_mgv_t *)apr_pcalloc(p, sizeof(*anon)); + + anon->name = apr_psprintf(p, "%d", modperl_global_anon_cnt_next()); + anon->len = strlen(anon->name); + PERL_HASH(anon->hash, anon->name, anon->len); + + MP_TRACE_h(MP_FUNC, "[%s] new anon handler: '%s'", + modperl_pid_tid(p), anon->name); + return anon; +} + +MP_INLINE void modperl_handler_anon_add(pTHX_ modperl_mgv_t *anon, CV *cv) +{ + modperl_modglobal_key_t *gkey = + modperl_modglobal_lookup(aTHX_ "ANONSUB"); + HE *he = MP_MODGLOBAL_FETCH(gkey); + HV *hv; + + if (!(he && (hv = (HV*)HeVAL(he)))) { + Perl_croak(aTHX_ "can't find ANONSUB top entry (get)"); + } + + SvREFCNT_inc(cv); + if (!(*hv_store(hv, anon->name, anon->len, (SV*)cv, anon->hash))) { + SvREFCNT_dec(cv); + Perl_croak(aTHX_ "hv_store of '%s' has failed!", anon->name); + } + + MP_TRACE_h(MP_FUNC, "anonsub '%s' added", anon->name); +} + +MP_INLINE CV *modperl_handler_anon_get(pTHX_ modperl_mgv_t *anon) +{ + modperl_modglobal_key_t *gkey = + modperl_modglobal_lookup(aTHX_ "ANONSUB"); + HE *he = MP_MODGLOBAL_FETCH(gkey); + HV *hv; + SV *sv; + + if (!(he && (hv = (HV*)HeVAL(he)))) { + Perl_croak(aTHX_ "can't find ANONSUB top entry (get)"); + } + + if ((he = hv_fetch_he(hv, anon->name, anon->len, anon->hash))) { + sv = HeVAL(he); + MP_TRACE_h(MP_FUNC, "anonsub get '%s'", anon->name); + } + else { + Perl_croak(aTHX_ "can't find ANONSUB's '%s' entry", anon->name); + } + + return (CV*)sv; +} static modperl_handler_t *modperl_handler_new_anon(pTHX_ apr_pool_t *p, CV *cv) @@ -53,34 +162,16 @@ MpHandlerANON_On(handler); #ifdef USE_ITHREADS - /* XXX: perhaps we can optimize this further. At the moment when - * perl w/ ithreads is used, we always deparse the anon subs - * before storing them and then eval them each time they are - * used. This is because we don't know whether the same perl that - * compiled the anonymous sub is used to run it. - * - * A possible optimization is to cache the CV and use that cached - * value w/ or w/o deparsing at all if: - * - * - the mpm is non-threaded mpm and no +Clone/+Parent is used - * (i.e. no perl pools) (no deparsing is needed at all) - * - * - the interpreter that has supplied the anon cv is the same - * interpreter that is executing that cv (requires storing aTHX - * in the handler's struct) (need to deparse in case the - * interpreter gets switched) - * - * - other cases? - */ - handler->cv = NULL; - handler->name = modperl_coderef2text(aTHX_ p, cv); - MP_TRACE_h(MP_FUNC, "[%s] new deparsed anon handler:\n%s\n", - modperl_pid_tid(p), handler->name); + handler->cv = NULL; + handler->name = NULL; + handler->mgv_obj = modperl_handler_anon_next(aTHX_ p); + modperl_handler_anon_add(aTHX_ handler->mgv_obj, cv); #else /* it's safe to cache and later use the cv, since the same perl * interpeter is always used */ - handler->cv = cv; + handler->cv = cv; handler->name = NULL; + MP_TRACE_h(MP_FUNC, "[%s] new cached cv anon handler\n", modperl_pid_tid(p)); #endif Modified: perl/modperl/trunk/src/modules/perl/modperl_handler.h Url: http://svn.apache.org/viewcvs/perl/modperl/trunk/src/modules/perl/modperl_handler.h?view=diff&rev=106450&p1=perl/modperl/trunk/src/modules/perl/modperl_handler.h&r1=106449&p2=perl/modperl/trunk/src/modules/perl/modperl_handler.h&r2=106450 ============================================================================== --- perl/modperl/trunk/src/modules/perl/modperl_handler.h (original) +++ perl/modperl/trunk/src/modules/perl/modperl_handler.h Wed Nov 24 11:32:47 2004 @@ -22,6 +22,11 @@ MP_HANDLER_ACTION_SET } modperl_handler_action_e; +void modperl_handler_anon_init(pTHX_ apr_pool_t *p); +MP_INLINE modperl_mgv_t *modperl_handler_anon_next(pTHX_ apr_pool_t *p); +MP_INLINE void modperl_handler_anon_add(pTHX_ modperl_mgv_t *anon, CV *cv); +MP_INLINE CV *modperl_handler_anon_get(pTHX_ modperl_mgv_t *anon); + #define modperl_handler_array_new(p) \ apr_array_make(p, 1, sizeof(modperl_handler_t *)) Modified: perl/modperl/trunk/src/modules/perl/modperl_mgv.c Url: http://svn.apache.org/viewcvs/perl/modperl/trunk/src/modules/perl/modperl_mgv.c?view=diff&rev=106450&p1=perl/modperl/trunk/src/modules/perl/modperl_mgv.c&r1=106449&p2=perl/modperl/trunk/src/modules/perl/modperl_mgv.c&r2=106450 ============================================================================== --- perl/modperl/trunk/src/modules/perl/modperl_mgv.c (original) +++ perl/modperl/trunk/src/modules/perl/modperl_mgv.c Wed Nov 24 11:32:47 2004 @@ -193,9 +193,35 @@ } if (strnEQ(name, "sub ", 4)) { - MP_TRACE_h(MP_FUNC, "handler is anonymous\n"); - MpHandlerANON_On(handler); + SV *sv; + CV *cv; MpHandlerPARSED_On(handler); + MpHandlerANON_On(handler); + + ENTER;SAVETMPS; + sv = eval_pv(name, TRUE); + if (!(SvROK(sv) && (cv = (CV*)SvRV(sv)) && (CvFLAGS(cv) & CVf_ANON))) { + + Perl_croak(aTHX_ "expected anonymous sub, got '%s'\n", name); + } + +#ifdef USE_ITHREADS + handler->cv = NULL; + handler->name = NULL; + handler->mgv_obj = modperl_handler_anon_next(aTHX_ p); + modperl_handler_anon_add(aTHX_ handler->mgv_obj, cv); + MP_TRACE_h(MP_FUNC, "[%s] new anon handler", + modperl_pid_tid(p)); +#else + SvREFCNT_inc(cv); + handler->cv = cv; + handler->name = NULL; + MP_TRACE_h(MP_FUNC, "[%s] new cached-cv anon handler", + modperl_pid_tid(p)); +#endif + + FREETMPS;LEAVE; + return 1; } Modified: perl/modperl/trunk/src/modules/perl/modperl_perl_global.c Url: http://svn.apache.org/viewcvs/perl/modperl/trunk/src/modules/perl/modperl_perl_global.c?view=diff&rev=106450&p1=perl/modperl/trunk/src/modules/perl/modperl_perl_global.c&r1=106449&p2=perl/modperl/trunk/src/modules/perl/modperl_perl_global.c&r2=106450 ============================================================================== --- perl/modperl/trunk/src/modules/perl/modperl_perl_global.c (original) +++ perl/modperl/trunk/src/modules/perl/modperl_perl_global.c Wed Nov 24 11:32:47 2004 @@ -15,30 +15,14 @@ #include "mod_perl.h" -static void modperl_perl_global_init(pTHX_ modperl_perl_globals_t *globals) -{ - globals->env.gv = PL_envgv; - globals->inc.gv = PL_incgv; - globals->defout.gv = PL_defoutgv; - globals->rs.sv = &PL_rs; - globals->end.av = &PL_endav; - globals->end.key = MP_MODGLOBAL_END; -} - /* XXX: PL_modglobal thingers might be useful elsewhere */ -#define MP_MODGLOBAL_FETCH(gkey) \ - hv_fetch_he(PL_modglobal, (char *)gkey->val, gkey->len, gkey->hash) - -#define MP_MODGLOBAL_STORE_HV(gkey) \ - (HV*)*hv_store(PL_modglobal, gkey->val, gkey->len, \ - (SV*)newHV(), gkey->hash) - #define MP_MODGLOBAL_ENT(key) \ {key, "ModPerl::" key, MP_SSTRLEN("ModPerl::") + MP_SSTRLEN(key), 0} static modperl_modglobal_key_t MP_modglobal_keys[] = { MP_MODGLOBAL_ENT("END"), + MP_MODGLOBAL_ENT("ANONSUB"), { NULL }, }; @@ -64,6 +48,16 @@ } return NULL; +} + +static void modperl_perl_global_init(pTHX_ modperl_perl_globals_t *globals) +{ + globals->env.gv = PL_envgv; + globals->inc.gv = PL_incgv; + globals->defout.gv = PL_defoutgv; + globals->rs.sv = &PL_rs; + globals->end.av = &PL_endav; + globals->end.key = MP_MODGLOBAL_END; } /* Modified: perl/modperl/trunk/src/modules/perl/modperl_perl_global.h Url: http://svn.apache.org/viewcvs/perl/modperl/trunk/src/modules/perl/modperl_perl_global.h?view=diff&rev=106450&p1=perl/modperl/trunk/src/modules/perl/modperl_perl_global.h&r1=106449&p2=perl/modperl/trunk/src/modules/perl/modperl_perl_global.h&r2=106450 ============================================================================== --- perl/modperl/trunk/src/modules/perl/modperl_perl_global.h (original) +++ perl/modperl/trunk/src/modules/perl/modperl_perl_global.h Wed Nov 24 11:32:47 2004 @@ -16,6 +16,13 @@ #ifndef MODPERL_PERL_GLOBAL_H #define MODPERL_PERL_GLOBAL_H +#define MP_MODGLOBAL_FETCH(gkey) \ + hv_fetch_he(PL_modglobal, (char *)gkey->val, gkey->len, gkey->hash) + +#define MP_MODGLOBAL_STORE_HV(gkey) \ + (HV*)*hv_store(PL_modglobal, gkey->val, gkey->len, \ + (SV*)newHV(), gkey->hash) + typedef struct { const char *name; const char *val; Modified: perl/modperl/trunk/src/modules/perl/modperl_types.h Url: http://svn.apache.org/viewcvs/perl/modperl/trunk/src/modules/perl/modperl_types.h?view=diff&rev=106450&p1=perl/modperl/trunk/src/modules/perl/modperl_types.h&r1=106449&p2=perl/modperl/trunk/src/modules/perl/modperl_types.h&r2=106450 ============================================================================== --- perl/modperl/trunk/src/modules/perl/modperl_types.h (original) +++ perl/modperl/trunk/src/modules/perl/modperl_types.h Wed Nov 24 11:32:47 2004 @@ -176,13 +176,16 @@ typedef struct modperl_handler_t modperl_handler_t; -struct modperl_handler_t{ +struct modperl_handler_t { + /* could be: + * - the lightweight gv for named subs + * - the lookup data in $PL_modperl{ANONSUB} + */ modperl_mgv_t *mgv_obj; modperl_mgv_t *mgv_cv; /* could be: - * - a subroutine name - * - a subroutine source code as a string (anon subs) - * - NULL, when .cv is set (anon subs) + * - a subroutine name for named subs + * - NULL for anon subs */ const char *name; CV *cv; Modified: perl/modperl/trunk/src/modules/perl/modperl_util.c Url: http://svn.apache.org/viewcvs/perl/modperl/trunk/src/modules/perl/modperl_util.c?view=diff&rev=106450&p1=perl/modperl/trunk/src/modules/perl/modperl_util.c&r1=106449&p2=perl/modperl/trunk/src/modules/perl/modperl_util.c&r2=106450 ============================================================================== --- perl/modperl/trunk/src/modules/perl/modperl_util.c (original) +++ perl/modperl/trunk/src/modules/perl/modperl_util.c Wed Nov 24 11:32:47 2004 @@ -702,86 +702,6 @@ return package; } -char *modperl_coderef2text(pTHX_ apr_pool_t *p, CV *cv) -{ - dSP; - int count; - SV *bdeparse; - SV *use; - char *text; - int tainted_orig; - - /* B::Deparse >= 0.61 needed for blessed code references. - * 0.6 works fine for non-blessed code refs. - * notice that B::Deparse is not CPAN-updatable. - * 0.61 is available starting from 5.8.0 - */ - - /* - Perl_load_module(aTHX_ PERL_LOADMOD_NOIMPORT, - newSVpvn("B::Deparse", 10), - newSVnv(SvOBJECT((SV*)cv) ? 0.61 : 0.60)); - * Perl_load_module() was causing segfaults in the worker MPM. - * this is a work around until we can find the problem with - * Perl_load_module() - * See: http://marc.theaimsgroup.com/?t=109684579900001&r=1&w=2 - */ - use = newSVpv("use B::Deparse ", 15); - if (SvOBJECT((SV*)cv)) { - sv_catpvn(use, "0.61", 3); - } - sv_catpvn(use, " ();", 4); - - tainted_orig = PL_tainted; - TAINT_NOT; - eval_sv(use, G_DISCARD); - PL_tainted = tainted_orig; - sv_free(use); - - ENTER; - SAVETMPS; - - /* create the B::Deparse object */ - PUSHMARK(sp); - XPUSHs(sv_2mortal(newSVpvn("B::Deparse", 10))); - PUTBACK; - count = call_method("new", G_SCALAR); - SPAGAIN; - if (count != 1) { - Perl_croak(aTHX_ "Unexpected return value from B::Deparse::new\n"); - } - if (SvTRUE(ERRSV)) { - Perl_croak(aTHX_ "error: %s", SvPVX(ERRSV)); - } - bdeparse = POPs; - - PUSHMARK(sp); - XPUSHs(bdeparse); - XPUSHs(sv_2mortal(newRV_inc((SV*)cv))); - PUTBACK; - count = call_method("coderef2text", G_SCALAR); - SPAGAIN; - if (count != 1) { - Perl_croak(aTHX_ "Unexpected return value from " - "B::Deparse::coderef2text\n"); - } - if (SvTRUE(ERRSV)) { - Perl_croak(aTHX_ "error: %s", SvPVX(ERRSV)); - } - - { - STRLEN n_a; - text = apr_pstrcat(p, "sub ", POPpx, NULL); - } - - PUTBACK; - - FREETMPS; - LEAVE; - - return text; -} - SV *modperl_apr_array_header2avrv(pTHX_ apr_array_header_t *array) { AV *av = newAV(); Modified: perl/modperl/trunk/src/modules/perl/modperl_util.h Url: http://svn.apache.org/viewcvs/perl/modperl/trunk/src/modules/perl/modperl_util.h?view=diff&rev=106450&p1=perl/modperl/trunk/src/modules/perl/modperl_util.h&r1=106449&p2=perl/modperl/trunk/src/modules/perl/modperl_util.h&r2=106450 ============================================================================== --- perl/modperl/trunk/src/modules/perl/modperl_util.h (original) +++ perl/modperl/trunk/src/modules/perl/modperl_util.h Wed Nov 24 11:32:47 2004 @@ -96,14 +96,6 @@ char *modperl_file2package(apr_pool_t *p, const char *file); -/** - * convert a compiled *CV ref to its original source code - * @param p pool object (with a shortest possible life scope) - * @param cv compiled *CV - * @return string of original source code - */ -char *modperl_coderef2text(pTHX_ apr_pool_t *p, CV *cv); - SV *modperl_apr_array_header2avrv(pTHX_ apr_array_header_t *array); apr_array_header_t *modperl_avrv2apr_array_header(pTHX_ apr_pool_t *p, SV *avrv); Modified: perl/modperl/trunk/t/filter/both_str_req_add.t Url: http://svn.apache.org/viewcvs/perl/modperl/trunk/t/filter/both_str_req_add.t?view=diff&rev=106450&p1=perl/modperl/trunk/t/filter/both_str_req_add.t&r1=106449&p2=perl/modperl/trunk/t/filter/both_str_req_add.t&r2=106450 ============================================================================== --- perl/modperl/trunk/t/filter/both_str_req_add.t (original) +++ perl/modperl/trunk/t/filter/both_str_req_add.t Wed Nov 24 11:32:47 2004 @@ -5,7 +5,7 @@ use Apache::TestRequest; use Apache::TestUtil; -plan tests => 1, need_min_module_version('B::Deparse', 0.6); +plan tests => 1; my $data = join ' ', 'A'..'Z', 0..9; my $expected = lc $data; # that's what the input filter does Modified: perl/modperl/trunk/t/hooks/TestHooks/push_handlers_blessed.pm Url: http://svn.apache.org/viewcvs/perl/modperl/trunk/t/hooks/TestHooks/push_handlers_blessed.pm?view=diff&rev=106450&p1=perl/modperl/trunk/t/hooks/TestHooks/push_handlers_blessed.pm&r1=106449&p2=perl/modperl/trunk/t/hooks/TestHooks/push_handlers_blessed.pm&r2=106450 ============================================================================== --- perl/modperl/trunk/t/hooks/TestHooks/push_handlers_blessed.pm (original) +++ perl/modperl/trunk/t/hooks/TestHooks/push_handlers_blessed.pm Wed Nov 24 11:32:47 2004 @@ -19,7 +19,7 @@ sub handler { my $r = shift; - plan $r, tests => 1, need_min_module_version('B::Deparse', 0.61);; + plan $r, tests => 1; my $sub = sub { ok 1; Modified: perl/modperl/trunk/t/hooks/push_handlers.t Url: http://svn.apache.org/viewcvs/perl/modperl/trunk/t/hooks/push_handlers.t?view=diff&rev=106450&p1=perl/modperl/trunk/t/hooks/push_handlers.t&r1=106449&p2=perl/modperl/trunk/t/hooks/push_handlers.t&r2=106450 ============================================================================== --- perl/modperl/trunk/t/hooks/push_handlers.t (original) +++ perl/modperl/trunk/t/hooks/push_handlers.t Wed Nov 24 11:32:47 2004 @@ -5,7 +5,7 @@ use Apache::TestUtil; use Apache::TestRequest; -plan tests => 1, need_min_module_version('B::Deparse', 0.6); +plan tests => 1; my @refs = qw(conf conf1 conf2 coderef full_coderef coderef1 coderef2 coderef3);