develooper Front page | perl.perl5.porters | Postings from November 2008

[perl #60890] corrupts $SIG{__DIE__} in BEGIN blocks

Thread Next
John Siracusa
November 28, 2008 05:19
[perl #60890] corrupts $SIG{__DIE__} in BEGIN blocks
Message ID:
# New Ticket Created by  John Siracusa 
# Please include the string:  [perl #60890]
# in the subject line of all future correspondence about this issue. 
# <URL: >

This is a bug report for perl from,
generated with the help of perlbug 1.36 running under perl 5.10.0.

Much of this report is copied and pasted from the following URL:

Consider the following code:

      package MyEx;

      sub new { bless {}, shift }

      package main;

      eval { die MyEx->new };

        die "Really die"  unless($@->isa('MyEx'));

    print "OK\n";

Run it and it prints "OK" as expected.  Run it in the debugger, however,
and it dies with this error:

    Can't call method "isa" without a package or object reference ...

The upshot is that $@ is not an object when the code runs under the
debugger. Instead, it's an unblessed scalar containing this string:

    " at line 9
        eval {...} called at line 9
        main::BEGIN() called at line 16
        eval {...} called at line 16

(Internal newlines and spacing preserved.  That's the literal text of the
string, including the "..."s.)

Setting dieLevel to 0, either through the use of a ~/.perldb file containing:


or by setting the PERLDB_OPT environment variablt to "dieLevel=0", did not
solve the problem.

local()izing $SIG{__DIE__} inside the eval block is a workaround, but
should not be necessary and is not done in much real code.  This makes it
impossible to use the debugger during the development of such code (e.g.,
several of my larger CPAN modules).

Here's an explanation of the bug from brian d foy:

This is a problem with creating __DIE__ handlers. If I localize
$SIG{__DIE__} in your eval, things work as you expect.

      local $SIG{__DIE__};
      die MyEx->new;

If you don't do that, you're getting the handler from DB::dbdie, which uses
Carp::longmess. That shouldn't happen if dieLevel is 0, but by default it
is 1, and it gets set to 1 if it is not defined. This was a patch to back in 2001, and previously the default had been 0.

You're supposed to turn this off with:

    PERLDB_OPT="dieLevel=0" perl5.10.0 -d program

But there is still a code reference in $SIG{__DIE__} after that, and it's a
reference to dbdie. I think this is a bug in handling the global variable
$prevdie in's dieLevel. At the end of that subroutine, there is:

       # dieLevel, around line 7777
       elsif ($prevdie) {
            $SIG{__DIE__} = $prevdie;
            print $OUT "Default die handler restored.\n";

But notice that after restoring $SIG{__DIE__}, it keeps the previous value
in $prevdie, meaning whatever is in there leaks to another call. When I run
that command line, there are two calls to dieLevel before it handles
PERLDB_OPT, so $prevdie is probably dirty.

So, that's as far as I got before I didn't want to think about

It seems like another workaround could be to change the default dieLevel
back to 0 instead of 1.

BTW, the "perldoc perldebug" documentation seems to imply that the default
value of dieLevel is still 0:

    "By default, the debugger leaves your exceptions and warnings alone,
     because altering them can break correctly running programs."

so apparently that patch in 2001 that brian refers to only updated the
code, but not the docs.


Site configuration information for perl 5.10.0:

Configured by john at Sat Sep 20 20:27:53 EDT 2008.

Summary of my perl5 (revision 5 version 10 subversion 0) configuration:
    osname=darwin, osvers=9.5.0, archname=darwin-2level
    uname='darwin link.local 9.5.0 darwin kernel version 9.5.0: wed
sep 3 11:29:43 pdt 2008; root:xnu-1228.7.58~1release_i386 i386 '
    hint=recommended, useposix=true, d_sigaction=define
    useithreads=undef, usemultiplicity=undef
    useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef
    use64bitint=undef, use64bitall=undef, uselongdouble=undef
    usemymalloc=n, bincompat5005=undef
    cc='cc', ccflags ='-fno-common -DPERL_DARWIN -no-cpp-precomp
-fno-strict-aliasing -pipe -I/usr/local/include',
    cppflags='-no-cpp-precomp -fno-common -DPERL_DARWIN
-no-cpp-precomp -fno-strict-aliasing -pipe -I/usr/local/include'
    ccversion='', gccversion='4.0.1 (Apple Inc. build 5488)', gccosandvers=''
    intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234
    d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16
    ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t',
    alignbytes=8, prototype=define
  Linker and Libraries:
    ld='env MACOSX_DEPLOYMENT_TARGET=10.3 cc', ldflags =' -L/usr/local/lib'
    libpth=/usr/local/lib /usr/lib
    libs=-ldbm -ldl -lm -lutil -lc
    perllibs=-ldl -lm -lutil -lc
    libc=/usr/lib/libc.dylib, so=dylib, useshrplib=false, libperl=libperl.a
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=bundle, d_dlsymun=undef, ccdlflags=' '
    cccdlflags=' ', lddlflags=' -bundle -undefined dynamic_lookup

Locally applied patches:

@INC for perl 5.10.0:

Environment for perl 5.10.0:
    LANGUAGE (unset)
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    PERL_BADLANG (unset)

Thread Next Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at | Group listing | About