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)

Reply via email to