Hi! perl: 5.10.1, 5.12.1 (i686-linux, x86_64-linux) mod_perl: 2.0.4
Basically if you have end blocks that modify/add END blocks things might go crazy. A simple test case for this is: package test: END { eval "END { }" for 1..10 } gives: Not a CODE reference. END failed--call queue aborted. if I add another END {}: package test: END { eval "END { }" for 1..10 } END { } I get: Undefined subroutine &main:: called. END failed--call queue aborted. This was found as I was getting strange segfaults when trying to use NYTProf. Nicholas Clark was able to pinpoint the problem. See: http://groups.google.com/group/develnytprof-dev/msg/4ff26e6b3d95861f thread: http://groups.google.com/group/develnytprof-dev/browse_thread/thread/20d2ea800e8936f Ive included some relevant bits here (again from Nicholas): > Of course, I looked at the core perl source to see how END blocks were run, > and the behaviour was safe with perl. perl unshifts each CV from the list > before it calls it. I should have remembered that inevitably mod_perl is > "special". > > On reflection, I think that this *is* a bug in mod_perl, as they're going > to get tripped up in similar fashion if any code run as part of an END block > contains a string eval containing an END block. Now the simple fix would be to just make modperl shift things off as well (see attached patch to make it use Perl_call_list). Course if they use ModPerl::Global::special_list_(call|clear) like t/modperl/endav.t things break. As when we go to run END blocks or call special_list_call() they will have been shifted off. This might be acceptable behavior for END blocks, but I can see not wanting to break other things that use modperl_perl_call_use. Maybe, maybe not. Thoughts? Another option would be to copy/local() the array in modpler_perl_call_list. Of course that still wont get it "right" because we wont run any newly defined subs... But at least we wont segfault/crap out. Thoughts?
--- modperl_util.c.orig 2010-06-28 10:58:53.535686254 -0600 +++ modperl_util.c 2010-06-28 11:01:25.059112059 -0600 @@ -467,30 +467,12 @@ void modperl_perl_call_list(pTHX_ AV *subs, const char *name) { - I32 i, oldscope = PL_scopestack_ix; - SV **ary = AvARRAY(subs); - MP_TRACE_g(MP_FUNC, "pid %lu" MP_TRACEf_TID MP_TRACEf_PERLID " running %d %s subs", (unsigned long)getpid(), MP_TRACEv_TID_ MP_TRACEv_PERLID_ AvFILLp(subs)+1, name); - for (i=0; i<=AvFILLp(subs); i++) { - CV *cv = (CV*)ary[i]; - SV *atsv = ERRSV; - - PUSHMARK(PL_stack_sp); - call_sv((SV*)cv, G_EVAL|G_DISCARD); - - if (SvCUR(atsv)) { - Perl_sv_catpvf(aTHX_ atsv, "%s failed--call queue aborted", - name); - while (PL_scopestack_ix > oldscope) { - LEAVE; - } - Perl_croak(aTHX_ "%s", SvPVX(atsv)); - } - } + Perl_call_list(aTHX_ PL_scopestack_ix, subs); } void modperl_perl_exit(pTHX_ int status)