Skip Menu |
Report information
Id: 831
Status: resolved
Priority: 0/
Queue: perl5

Owner: Nobody
Requestors: Richard.Foley [at] m.dasa.de
Cc:
AdminCc:

Operating System: Linux
PatchStatus: (no value)
Severity: medium
Type: (no value)
Perl Version: (no value)
Fixed In: (no value)



From: "Foley, Richard" <Richard.Foley [...] m.dasa.de>
To: brettle [...] his.com
Cc: perlbug [...] perl.org
Subject: WG: DESTROY() interferes with die()
Date: Tue, 1 Jun 1999 08:36:06 +0200
Download (untitled) / with headers
text/plain 6.1k
This report has been registered with perlbug. Von: perlbug@perl.org [mailto:perlbug@perl.org] Gesendet am: Tuesday, June 01, 1999 3:09 AM An: brettle@his.com Betreff: perlbug rejection: DESTROY() interferes with die() This email address is for reporting bugs to the perl community via perlbug@perl.org. Please address your mail appropriately and include output from the perlbug program as per the distributed documentation. Hint: mail should include 'perl -v' and it's output. From brettle@his.com Mon May 31 21:08:57 1999 Received: from jhereg.perl.com (IDENT:root@perl.com [199.45.135.9]) by defender.perl.org (8.9.3/8.9.3/Debian/GNU) with ESMTP id VAA30256 for <perlbugtron@perl.org>; Mon, 31 May 1999 21:08:53 -0400 From: brettle@his.com Received: from smtp1.mindspring.com (smtp1.mindspring.com [207.69.200.31]) by jhereg.perl.com (8.9.0/8.9.0) with ESMTP id QAA30568 for <perlbug@perl.com>; Mon, 31 May 1999 16:56:27 -0600 Received: from server.brettle.com (user-33qsua6.dialup.mindspring.com [199.174.121.70]) by smtp1.mindspring.com (8.8.5/8.8.5) with ESMTP id SAA13505; Mon, 31 May 1999 18:56:38 -0400 (EDT) Received: (from brettle@localhost) by server.brettle.com (8.8.7/8.8.7) id PAA19201; Mon, 31 May 1999 15:55:46 -0700 Date: Mon, 31 May 1999 15:55:46 -0700 Message-Id: <199905312255.PAA19201@server.brettle.com> To: perlbug@perl.com Subject: DESTROY() interferes with die() Cc: dean@brettle.com Reply-To: dean@brettle.com This is a bug report for perl from dean@brettle.com, generated with the help of perlbug 1.26 running under perl 5.00405. ----------------------------------------------------------------- Hi all, Here is a little perl which illustrates the problem. Commentary follows. package C; sub new { my $self = bless {}; return $self; } sub DESTROY { eval { print "This eval resets \$\@, which is BAD\n"; }; } eval { my $o = new C; die "This error should be caught but isn't"; }; if ($@) { print "Caught: $@"; } else { print "Error missed due to perl bug\n"; } Here is what is going on: 0. We eval some code, expecting to catch errors. 1. We create a C in some scope within the eval. In our example the scope is just the scope of the eval, but it could really be any scope contained within the eval. 2. Later in the scope, we die. This sets $@ and goes to the next line past our eval, exiting our scope in the process. 3. When Perl exits the scope, it invokes C->DESTROY() to clean up our object. 4. C->DESTROY() happens to contain an eval which doesn't die(). This *clears* $@. Oooops! 5. When we check $@ after our eval, it's empty. :-( This is a *really* evil bug because it means that anytime you create an object using someone else's package, you run the risk of completely hosing any exception handling you are doing. This bug was discussed approximately 1 year ago. Here's a link to the discussion: http://x43.deja.com/getdoc.xp?AN=389699069&CONTEXT=926789340.1861025869 I've found the bug in 5.004_04, 5.004_05 (both i386-linux), and according to Chuck O'Donnell it also exists in 5.005_03 (i386-freefsd). For my complete 'perl -V' see below. FWIW, I've run into this twice in the last 2 weeks. In both cases, I worked around it by patching the modules which triggered the problem. Unfortunately, due to $@'s unintuitive scoping, the workaround isn't quite as simple as adding 'local $@' at the beginning of each DESTROY. Instead, I needed to write a this psuedo-control construct which I wrap around the code executed in each DESTROY. # "carefully BLOCK LIST" executes BLOCK (with @_ = LIST) without # clearing $@. This is critical for DESTROY methods since they might # accidentally clear $@ by using an eval. sub carefully(&@) { my $block = shift; my $new_err; my @result; # $@ has strange scoping so just doing "local $@" is not # sufficient. For discussion see: # http://x28.deja.com/getdoc.xp?AN=339328324&CONTEXT=926784629.777191445 { local $@; @result = eval { $block->(@_); }; $new_err = $@; } die $new_err if ($new_err && !$@); warn $new_err if ($new_err && $@); return @result; } Any idea when the die/DESTROY bug will be fixed? Many thanks to all of you for all the time and energy you put into perl! Cheers, --Dean +--------------------------------------------------------------------+ | Dean Brettle Computer Consulting http://www.brettle.com/ | | Contract development and support of software and systems | +--------------------------------------------------------------------+ [Please do not change anything below this line] ----------------------------------------------------------------- --- Site configuration information for perl 5.00405: Configured by root at Mon May 31 15:33:19 PDT 1999. Summary of my perl5 (5.0 patchlevel 4 subversion 5) configuration: Platform: osname=linux, osvers=2.0.36, archname=i386-linux uname='linux server 2.0.36 #2 sun may 23 13:15:45 pdt 1999 i586 unknown ' hint=recommended, useposix=true, d_sigaction=define bincompat3=y useperlio=undef d_sfio=undef Compiler: cc='cc', optimize='-O2', gccversion=2.7.2.3 cppflags='-Dbool=char -DHAS_BOOL' ccflags ='-Dbool=char -DHAS_BOOL' stdchar='char', d_stdstdio=define, usevfork=false intsize=4, longsize=4, ptrsize=undef, doublesize=undef alignbytes=4, usemymalloc=n, prototype=define Linker and Libraries: ld='cc', ldflags =' -L/usr/local/lib' libpth=/usr/local/lib /lib /usr/lib libs=-lnsl -lndbm -lgdbm -ldb -ldl -lm -lc -lposix -lcrypt libc=, so=so useshrplib=false, libperl=libperl.a Dynamic Linking: dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-rdynamic' cccdlflags='-fpic', lddlflags='-shared -L/usr/local/lib' Locally applied patches: MAINT_TRIAL_7 - 5.004_05 maintenance trial 7 --- @INC for perl 5.00405: /usr/lib/perl5/i386-linux/5.00405 /usr/lib/perl5 /usr/lib/perl5/site_perl/i386-linux /usr/lib/perl5/site_perl . --- Environment for perl 5.00405: HOME=/home/brettle LANG (unset) LD_LIBRARY_PATH (unset) LOGDIR (unset) PATH=/usr/local/bin:/bin:/usr/bin:/usr/X11R6/bin PERL_BADLANG (unset) SHELL=/bin/bash
Subject: [ID 19990601.003] WG: DESTROY() interferes with die()
To: perl5-porters [...] perl.org
From: "Foley, Richard" <Richard.Foley [...] m.dasa.de>
Cc: perlbug [...] perl.org
Date: Tue, 1 Jun 1999 08:36:06 +0200
Download (untitled) / with headers
text/plain 6.2k
Perlbugtron missed this, I shall fix this immediately. This report has been registered with perlbug. Von: perlbug@perl.org [mailto:perlbug@perl.org] Gesendet am: Tuesday, June 01, 1999 3:09 AM An: brettle@his.com Betreff: perlbug rejection: DESTROY() interferes with die() This email address is for reporting bugs to the perl community via perlbug@perl.org. Please address your mail appropriately and include output from the perlbug program as per the distributed documentation. Hint: mail should include 'perl -v' and it's output. From brettle@his.com Mon May 31 21:08:57 1999 Received: from jhereg.perl.com (IDENT:root@perl.com [199.45.135.9]) by defender.perl.org (8.9.3/8.9.3/Debian/GNU) with ESMTP id VAA30256 for <perlbugtron@perl.org>; Mon, 31 May 1999 21:08:53 -0400 From: brettle@his.com Received: from smtp1.mindspring.com (smtp1.mindspring.com [207.69.200.31]) by jhereg.perl.com (8.9.0/8.9.0) with ESMTP id QAA30568 for <perlbug@perl.com>; Mon, 31 May 1999 16:56:27 -0600 Received: from server.brettle.com (user-33qsua6.dialup.mindspring.com [199.174.121.70]) by smtp1.mindspring.com (8.8.5/8.8.5) with ESMTP id SAA13505; Mon, 31 May 1999 18:56:38 -0400 (EDT) Received: (from brettle@localhost) by server.brettle.com (8.8.7/8.8.7) id PAA19201; Mon, 31 May 1999 15:55:46 -0700 Date: Mon, 31 May 1999 15:55:46 -0700 Message-Id: <199905312255.PAA19201@server.brettle.com> To: perlbug@perl.com Subject: DESTROY() interferes with die() Cc: dean@brettle.com Reply-To: dean@brettle.com This is a bug report for perl from dean@brettle.com, generated with the help of perlbug 1.26 running under perl 5.00405. ----------------------------------------------------------------- Hi all, Here is a little perl which illustrates the problem. Commentary follows. package C; sub new { my $self = bless {}; return $self; } sub DESTROY { eval { print "This eval resets \$\@, which is BAD\n"; }; } eval { my $o = new C; die "This error should be caught but isn't"; }; if ($@) { print "Caught: $@"; } else { print "Error missed due to perl bug\n"; } Here is what is going on: 0. We eval some code, expecting to catch errors. 1. We create a C in some scope within the eval. In our example the scope is just the scope of the eval, but it could really be any scope contained within the eval. 2. Later in the scope, we die. This sets $@ and goes to the next line past our eval, exiting our scope in the process. 3. When Perl exits the scope, it invokes C->DESTROY() to clean up our object. 4. C->DESTROY() happens to contain an eval which doesn't die(). This *clears* $@. Oooops! 5. When we check $@ after our eval, it's empty. :-( This is a *really* evil bug because it means that anytime you create an object using someone else's package, you run the risk of completely hosing any exception handling you are doing. This bug was discussed approximately 1 year ago. Here's a link to the discussion: http://x43.deja.com/getdoc.xp?AN=389699069&CONTEXT=926789340.1861025869 I've found the bug in 5.004_04, 5.004_05 (both i386-linux), and according to Chuck O'Donnell it also exists in 5.005_03 (i386-freefsd). For my complete 'perl -V' see below. FWIW, I've run into this twice in the last 2 weeks. In both cases, I worked around it by patching the modules which triggered the problem. Unfortunately, due to $@'s unintuitive scoping, the workaround isn't quite as simple as adding 'local $@' at the beginning of each DESTROY. Instead, I needed to write a this psuedo-control construct which I wrap around the code executed in each DESTROY. # "carefully BLOCK LIST" executes BLOCK (with @_ = LIST) without # clearing $@. This is critical for DESTROY methods since they might # accidentally clear $@ by using an eval. sub carefully(&@) { my $block = shift; my $new_err; my @result; # $@ has strange scoping so just doing "local $@" is not # sufficient. For discussion see: # http://x28.deja.com/getdoc.xp?AN=339328324&CONTEXT=926784629.777191445 { local $@; @result = eval { $block->(@_); }; $new_err = $@; } die $new_err if ($new_err && !$@); warn $new_err if ($new_err && $@); return @result; } Any idea when the die/DESTROY bug will be fixed? Many thanks to all of you for all the time and energy you put into perl! Cheers, --Dean +--------------------------------------------------------------------+ | Dean Brettle Computer Consulting http://www.brettle.com/ | | Contract development and support of software and systems | +--------------------------------------------------------------------+ [Please do not change anything below this line] ----------------------------------------------------------------- --- Site configuration information for perl 5.00405: Configured by root at Mon May 31 15:33:19 PDT 1999. Summary of my perl5 (5.0 patchlevel 4 subversion 5) configuration: Platform: osname=linux, osvers=2.0.36, archname=i386-linux uname='linux server 2.0.36 #2 sun may 23 13:15:45 pdt 1999 i586 unknown ' hint=recommended, useposix=true, d_sigaction=define bincompat3=y useperlio=undef d_sfio=undef Compiler: cc='cc', optimize='-O2', gccversion=2.7.2.3 cppflags='-Dbool=char -DHAS_BOOL' ccflags ='-Dbool=char -DHAS_BOOL' stdchar='char', d_stdstdio=define, usevfork=false intsize=4, longsize=4, ptrsize=undef, doublesize=undef alignbytes=4, usemymalloc=n, prototype=define Linker and Libraries: ld='cc', ldflags =' -L/usr/local/lib' libpth=/usr/local/lib /lib /usr/lib libs=-lnsl -lndbm -lgdbm -ldb -ldl -lm -lc -lposix -lcrypt libc=, so=so useshrplib=false, libperl=libperl.a Dynamic Linking: dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-rdynamic' cccdlflags='-fpic', lddlflags='-shared -L/usr/local/lib' Locally applied patches: MAINT_TRIAL_7 - 5.004_05 maintenance trial 7 --- @INC for perl 5.00405: /usr/lib/perl5/i386-linux/5.00405 /usr/lib/perl5 /usr/lib/perl5/site_perl/i386-linux /usr/lib/perl5/site_perl . --- Environment for perl 5.00405: HOME=/home/brettle LANG (unset) LD_LIBRARY_PATH (unset) LOGDIR (unset) PATH=/usr/local/bin:/bin:/usr/bin:/usr/X11R6/bin PERL_BADLANG (unset) SHELL=/bin/bash
Date: Mon, 20 Mar 2000 20:23:14 -0700 (MST)
From: Nathan Torkington <gnat [...] frii.com>
To: perl5-porters [...] perl.org
Cc: dean [...] brettle.com
Subject: [19990601.003] DESTROY() interferes with die()
Download (untitled) / with headers
text/plain 172b
Perl 5.6 will fix this. die() within DESTROY() is turned into a warn(), and so won't interfere with $@. I've marked the bug as closed. Thanks for your bug report, Nat


This service is sponsored and maintained by Best Practical Solutions and runs on Perl.org infrastructure.

For issues related to this RT instance (aka "perlbug"), please contact perlbug-admin at perl.org