Open p5pRT opened 23 years ago
Ouph\, this one took many hours to diagnose...
Here is the scoop:
In many situations doing die() after a require() is a kinda no-op.
Currently I can reproduce only one such situation:
perl_call_*() without G_EVAL called inside eval {}\,
but I believe many other contexts behave similarly.
Details of the control flow with the bug present: perl_call_*() does not return (!)\, but the Perl control is quietly (without longjmp()ing out of perl_call_*() (!)) transfered to the opcode after eval {}. When the script terminates\, the C control returns to perl_call_()\, then to the code which calls perl_call_*() and so on (with most data already DESTROYed!).
Example: dummy::callit() is an XSUB:
==================================================== void callit(void) { dSP;
PUSHMARK(SP); perl_call_pv("mysub"\, G_DISCARD|G_NOARGS); fprintf(stderr\, "finished call.\n"); }
MODULE = dummy PACKAGE = dummy
Perl code is:
==================================================== sub mysub { require less; die "ok 2\n" }
eval { dummy::callit(); warn "after!"; };
This prints:
Of course\, only the first line should be printed. [This is an extraction of what XML::Encoding is doing.]
Here are the debugging details: The bug happens when CATCH_GET() is true (this is why Perl_call_*() is doing)\, and in_eval is true too. The first condition ensures that pp_require() calls docatch(). Due to this pp_require() does not return when the end of the module is reached. Due to this\, the code after require() is still executed within the same docatch().
The second condition ensures that die_where() does not longjmp(). Then vdie() does longjmp(3)\, and docatch() essentially catches it\, and reenters again - and does not return from pp_require()/perl_call_*() - which leads to the behaviour described above.
Flags: category=core severity=critical
This perlbug was built using Perl v5.6.1 - Fri May 11 16:30:32 PDT 2001 It is being executed now by Perl v5.6.1 - Tue May 8 02:31:51 PDT 2001.
Site configuration information for perl v5.6.1:
Configured by vera at Tue May 8 02:31:51 PDT 2001.
Summary of my perl5 (revision 5.0 version 6 subversion 1) configuration: Platform: osname=os2\, osvers=2.30\, archname=os2 uname='os2 ia-ia 2 2.30 i386 ' config_args='-des -D prefix=j:/test/perllib' hint=recommended\, useposix=true\, d_sigaction=define usethreads=undef use5005threads=undef useithreads=undef usemultiplicity=undef useperlio=undef d_sfio=undef uselargefiles=define usesocks=undef use64bitint=undef use64bitall=undef uselongdouble=undef Compiler: cc='gcc'\, ccflags ='-Zomf -Zmt -DDOSISH -DOS2=2 -DEMBED -I. -D_EMX_CRT_REV_=63'\, optimize='-O2 -fomit-frame-pointer -malign-loops=2 -malign-jumps=2 -malign-functions=2 -s'\, cppflags='-Zomf -Zmt -DDOSISH -DOS2=2 -DEMBED -I. -D_EMX_CRT_REV_=63' ccversion=''\, gccversion='2.8.1'\, gccosandvers='' intsize=4\, longsize=4\, ptrsize=4\, doublesize=8\, byteorder=1234 d_longlong=define\, longlongsize=8\, d_longdbl=define\, longdblsize=12 ivtype='long'\, ivsize=4\, nvtype='double'\, nvsize=8\, Off_t='off_t'\, lseeksize=4 alignbytes=4\, usemymalloc=y\, prototype=define Linker and Libraries: ld='gcc'\, ldflags ='-Zexe -Zomf -Zmt -Zcrtdll -Zstack 32000' libpth=i:/emx.add/lib i:/emx/lib D:/DEVTOOLS/OPENGL/LIB I:/JAVA11/LIB i:/emx/lib/mt libs=-lsocket -lm -lbsd perllibs=-lsocket -lm -lbsd libc=i:/emx/lib/mt/c_import.lib\, so=dll\, useshrplib=true\, libperl=libperl.lib Dynamic Linking: dlsrc=dl_dlopen.xs\, dlext=dll\, d_dlsymun=undef\, ccdlflags=' ' cccdlflags='-Zdll'\, lddlflags='-Zdll -Zomf -Zmt -Zcrtdll -s'
Locally applied patches:
@INC for perl v5.6.1: j:/test/perllib/lib/5.6.1/os2 j:/test/perllib/lib/5.6.1 j:/test/perllib/lib/site_perl/5.6.1/os2 j:/test/perllib/lib/site_perl/5.6.1 j:/test/perllib/lib/site_perl .
Environment for perl v5.6.1: HOME=j:/home LANG=EN_US LANGUAGE (unset) LD_LIBRARY_PATH (unset) LOGDIR (unset) PATH=[censored] PERLLIB_PREFIX=f:/perllib;i:/perllib PERL_BADLANG (unset) PERL_SH_DIR=i:/bin SHELL (unset)
Since doing croak() will call a die() after require Carp::Heavy\, the failing sequence may be as easy as
From eval {} call an XSUB which calls (without G_EVAL) a Perl subroutine which croak()s
[Un]fortunately\, all XSUBs from Perl distribution which call Perl subroutines without G_EVAL do it from a "tie()ed method" context\, which replaces Perl stack\, and the above bug is not triggered when a stack is replaced.
There is only one exception - DProf. However\, (due to some DProf obfuscations?) I cannot see the effects of the bug with just calling croak(). However\, 'require less and die' shows the problem (segfault on my system\, I think it could print 12 nn some of other systems\, with other malloc()s).
perl -d:Dprof -wle " sub f {require less; die 'OO'} eval {f; print 12} or warn; print 13"
Hope this helps\, Ilya
Migrated from rt.perl.org#7020 (status was 'open')
Searchable as RT7020$