On 15 May 2015 at 07:14, Jan Kaluža <jkal...@redhat.com> wrote: > On 05/14/2015 07:42 PM, Steve Hay wrote: >> >> On 14 May 2015 at 12:48, Jan Kaluža <jkal...@redhat.com> wrote: >>> >>> On 05/14/2015 11:24 AM, Niko Tyni wrote: >>>> >>>> >>>> On Sun, May 10, 2015 at 01:47:19PM +0100, Steve Hay wrote: >>>>> >>>>> >>>>> On 28 April 2015 at 07:51, <jkal...@apache.org> wrote: >>>>>> >>>>>> >>>>>> Author: jkaluza >>>>>> Date: Tue Apr 28 06:51:12 2015 >>>>>> New Revision: 1676417 >>>>>> >>>>>> URL: http://svn.apache.org/r1676417 >>>>>> Log: >>>>>> Initialize interp->refcnt to 1 in modperl_interp_select. >>>> >>>> >>>> >>>>> I cannot understand why, but since this patch was applied I find that >>>>> t\modules\proxy.t fails every time when I run the full "nmake test", >>>>> but it always succeeds when I run it in isolation so I'm at a loss to >>>>> find out what is going wrong. All other tests (apart from those known >>>>> Win32-specific failures documented in README) still pass. Reverting >>>>> the patch "fixes" the proxy.t problem, but probably isn't the right >>>>> solution. >>> >>> >>> >>> It's caused by Perl_croak/modperl_croak. >>> >>> Lets take modperl_run_filter as an example. When following code-path is >>> executed ... >>> >>> modperl_croak(aTHX_ MODPERL_FILTER_ERROR, >>> "a filter calling $f->read " >>> "must return OK and not DECLINED"); >>> >>> ... the MP_INTERP_PUTBACK is not reached for some reason (I presume it's >>> because of Perl_croak, but I don't understand why it stops the execution >>> of >>> the rest of modperl_run_filter method). >>> >>> Because of that, the interp->refcnt is not decreased, and the interp is >>> not >>> freed. >>> >>> I has been able to "fix" it by attached patch, but I would like to >>> discuss >>> more generic way how to fix that problem... >>> >>> Any ideas? >>> >> >> modperl_croak() calls Perl_croak(), which is an XS interface to Perl's >> die() function, so surely you wouldn't expect anything immediately >> after it to be run? >> >> I'm not sure exactly where it does end up, though. It must be getting >> caught by some eval somewhere since we aren't exiting the process, but >> presumably it wouldn't be possible to do appropriate clean-up wherever >> it lands up unless there is some mechanism for registering required >> clean-up behaviour? Otherwise maybe we need to pass interp into >> modperl_croak(), or into a new version of that if not all cases >> require it, so that it can do the MP_INTERP_PUTBACK(interp, aTHX) >> call? >> > > What worries me here a bit is that we would have to MP_INTEPR_PUTBACK the > PerlInterp which is later used for PerlCroak, if I understand it right. > > I have found out that usually when modperl_croak is called, the refcnt of > the interp is above 1, so it wouldn't get freed prematurely, but still. > > I think for now we should putback the interp only when interp->refcnt > 1, > it wouldn't fully fix all bugs, but lot of them would be fixed by that. > > If someone knows how Perl_croak works and if it's possible to cleanup the > interp after that, it would be great to share that info . >
My understanding of Perl_croak() is that it either exits the process (if not inside an eval()) or else calls the system's longjmp(), which resumes execution from immediately after where the corresponding setjmp() was called, having restored the process environment to the original state at that point too. In the perl source, the setjmp()/longjmp() of eval()/die() are done by the JMPENV_PUSH in Perl_eval_sv() (maybe called from Perl_eval_pv()) and the JMPENV_JUMP in Perl_die_unwind(), called from Perl_vcroak(). The JMPENV* macros are in cop.h, and call PerlProc_setjmp()/PerlProc_longjmp(), which are typically setjmp()/longjmp(), or maybe sigsetjmp()/siglongjmp() if you have them. I think you're right that we should probably check that interp->refcnt > 1 if we go ahead and pass interp into modperl_croak(). There aren't too many calls, so this may be workable; we also have a few call MP_RUN_CROAK()/MP_RUN_CROAK_RESET() calls to look at too. What worries me is the (much larger number of!) calls to Perl_croak(). They will also not return, so we presumably need to do cleanup before each one of those too? Maybe we need a little wrapper function/macro to do clean up and then call Perl_croak() and use that everywhere instead of Perl_croak() (including the call inside modperl_croak(), of course)? --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@perl.apache.org For additional commands, e-mail: dev-h...@perl.apache.org