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)