Perl / perl5

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

Fwd: Re: FIX: Apache::Session & perl die/DESTROY bug #1162

Closed p5pRT closed 20 years ago

p5pRT commented 24 years ago

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

Searchable as RT2129$

p5pRT commented 24 years ago

From mike@blakeley.com

I really hope that I'm not wasting your time. This appears to be a scoping bug in perl up to and including 5.0005_03. I have not checked developer releases.

For background\, from http​://www.bitmechanic.com/mail-archives/modperl/May1999/0943.html

FIX​: Apache​::Session & perl die/DESTROY bug

dean@​brettle.com Sat\, 29 May 1999 12​:08​:59 -0700

For the second time in as many weeks I've been bitten by a bug in perl 5.004's error handling. The first time the bug was triggered by DBIx​::Recordset-0.19beta. This time\, the same bug is triggered by Apache​::Session-0.99.8. I've attached a patch (use patch -p1).

Here is a test case to illustrate the problem​:

use Apache​::Session; use Apache​::Session​::File;

eval { my %session; tie (%session\, 'Apache​::Session​::File'\, undef); $session{'foo'} = 'bar'; die "This error should be caught but isn't"; };

if ($@​) { print "Success​: Error caught.\n"; } else { print "Failure​: 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 an object in some scope within the eval. In our example the object is a hash tied to an Apache​::Session​::File and the scope is just the scope of the eval\, but it could really be any object and 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 our object's DESTROY() to clean it up.

4. DESTROY() happens to contain an eval which doesn't die(). This *clears* $@​. Oooops! In the case of Apache​::Session\, this eval is actually appears to be inside Storable's nstore_fd. Storable is used by Apache​::Session​::File.

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 appears to be an acknowledged bug in perl as of 5.004_05. I don't know about 5.005. Can someone who has 5.005 installed tell me if the above test script works correctly?

For more info on the bug\, see​:

http​://x43.deja.com/getdoc.xp?AN=389699069&CONTEXT=926789340.1861025869

Unfortunately\, due to $@​'s unintuitive scoping\, a complete solution isn't quite as simple as adding 'local $@​' at the beginning of each DESTROY. Instead\, I needed to write a psuedo-control construct (Apache​::Session​::Destroy​::carefully) which I wrap around the code executed in each DESTROY. For more info on $@​'s unintuitive scoping\, see​:

http​://x28.deja.com/getdoc.xp?AN=339328324&CONTEXT=926784629.777191445

I've removed the workaround patch that Dean gives for Apache​::Session. Suffice to say that this issue/bug/whatever still exists in 5.003_05​:

Date​: Wed\, 09 Feb 2000 20​:44​:34 -0800 From​: Dean Brettle \dean@​brettle\.com To​: Michael Blakeley \mike@​blakeley\.com Subject​: Re​: FIX​: Apache​::Session & perl die/DESTROY bug

Michael Blakeley wrote​:

I saw your mod_perl article on the $@​ scoping problem in perl 5.003. So just FYI...

$ perl -v

This is perl\, version 5.005_03 built for sun4-solaris

$ perl use Apache​::Session; use Apache​::Session​::File;

eval { my %session; tie (%session\, 'Apache​::Session​::File'\, undef); $session{'foo'} = 'bar'; die "This error should be caught but isn't"; };

if ($@​) { print "Success​: Error caught.\n"; } else { print "Failure​: Error missed due to perl bug.\n"; } Failure​: Error missed due to perl bug. $

Sigh...

Did you ever get any p5p feedback on this?

Nope. I posted it but never got any response.

And so I decided to post to this list\, myself. Again\, I hope that I'm not simply wasting your time. Having run into this problem myself (and been suprised\, since the example code for Apache​::Session expects $@​ to scope properly)\, I'd love to hear that this has been fixed. Yes\, I should pull the latest source and do it myself - but I'm a much better gadfly than I am a C programmer.

-- Mike

p5pRT commented 23 years ago

From [Unknown Contact. See original ticket]

This is not a bug in perl\, but rather a misdesign. Exception handling in Perl is clunky due to $@​ being global. That is why so many people have written Exception modules. Unfortunately\, a lot of library code does not properly localize $@​ when using eval. Those libraries cannot be used with other code that handles exceptions.

Here is how I typically write a try/catch​:

  my ($err);   {   local ($@​);   eval { stuff(); };   $err = $@​;   }   if ($err) {   if (! handle_exception($err)) {   die $err;   }   }

Or\, if the return value and context are important\, something like​:

  my ($ret\, $err);   {   local ($@​);   if (wantarray) {   $ret = [ eval { stuff() } ];   } else {   $ret = eval { stuff() };   }   $err = $@​;   }   if ($err) {   handle_exception($err) || die $err;   }   if (wantarray) {   return @​$ret;   } else {   return $ret;   }

The bug report should be closed. -John

On Wed\, 9 Feb 2000\, Michael Blakeley \mike@​blakeley\.com wrote​:

I really hope that I'm not wasting your time. This appears to be a scoping bug in perl up to and including 5.0005_03. I have not checked developer releases.

For background\, from http​://www.bitmechanic.com/mail-archives/modperl/May1999/0943.html

FIX​: Apache​::Session & perl die/DESTROY bug

dean@​brettle.com Sat\, 29 May 1999 12​:08​:59 -0700

For the second time in as many weeks I've been bitten by a bug in perl 5.004's error handling. The first time the bug was triggered by DBIx​::Recordset-0.19beta. This time\, the same bug is triggered by Apache​::Session-0.99.8. I've attached a patch (use patch -p1).

Here is a test case to illustrate the problem​:

use Apache​::Session; use Apache​::Session​::File;

eval { my %session; tie (%session\, 'Apache​::Session​::File'\, undef); $session{'foo'} = 'bar'; die "This error should be caught but isn't"; };

if ($@​) { print "Success​: Error caught.\n"; } else { print "Failure​: 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 an object in some scope within the eval. In our example the object is a hash tied to an Apache​::Session​::File and the scope is just the scope of the eval\, but it could really be any object and 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 our object's DESTROY() to clean it up.

4. DESTROY() happens to contain an eval which doesn't die(). This *clears* $@​. Oooops! In the case of Apache​::Session\, this eval is actually appears to be inside Storable's nstore_fd. Storable is used by Apache​::Session​::File.

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 appears to be an acknowledged bug in perl as of 5.004_05. I don't know about 5.005. Can someone who has 5.005 installed tell me if the above test script works correctly?

For more info on the bug\, see​:

http​://x43.deja.com/getdoc.xp?AN=389699069&CONTEXT=926789340.1861025869

Unfortunately\, due to $@​'s unintuitive scoping\, a complete solution isn't quite as simple as adding 'local $@​' at the beginning of each DESTROY. Instead\, I needed to write a psuedo-control construct (Apache​::Session​::Destroy​::carefully) which I wrap around the code executed in each DESTROY. For more info on $@​'s unintuitive scoping\, see​:

http​://x28.deja.com/getdoc.xp?AN=339328324&CONTEXT=926784629.777191445

I've removed the workaround patch that Dean gives for Apache​::Session. Suffice to say that this issue/bug/whatever still exists in 5.003_05​:

Date​: Wed\, 09 Feb 2000 20​:44​:34 -0800 From​: Dean Brettle \dean@​brettle\.com To​: Michael Blakeley \mike@​blakeley\.com Subject​: Re​: FIX​: Apache​::Session & perl die/DESTROY bug

Michael Blakeley wrote​:

I saw your mod_perl article on the $@​ scoping problem in perl 5.003. So just FYI...

$ perl -v

This is perl\, version 5.005_03 built for sun4-solaris

$ perl use Apache​::Session; use Apache​::Session​::File;

eval { my %session; tie (%session\, 'Apache​::Session​::File'\, undef); $session{'foo'} = 'bar'; die "This error should be caught but isn't"; };

if ($@​) { print "Success​: Error caught.\n"; } else { print "Failure​: Error missed due to perl bug.\n"; } Failure​: Error missed due to perl bug. $