Perl / perl5

🐪 The Perl programming language
https://dev.perl.org/perl5/
Other
1.96k stars 555 forks source link

WG: DESTROY() interferes with die() #31

Closed p5pRT closed 20 years ago

p5pRT commented 25 years ago

Migrated from rt.perl.org#831 (status was 'resolved')

Searchable as RT831$

p5pRT commented 25 years ago

From Richard.Foley@m.dasa.de

Created by dean@brettle.com

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 | +--------------------------------------------------------------------+

Perl Info ``` 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 ```
p5pRT commented 25 years ago

From [Unknown Contact. See original ticket]

Created by dean@brettle.com

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 | +--------------------------------------------------------------------+

Perl Info ``` 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 ```
p5pRT commented 24 years ago

From [Unknown Contact. See original ticket]

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