Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
p5pRT opened this issue Feb 9, 2000 · 2 comments
Closed

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

p5pRT opened this issue Feb 9, 2000 · 2 comments

Comments

@p5pRT
Copy link

p5pRT commented Feb 9, 2000

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

Searchable as RT2129$

@p5pRT
Copy link
Author

p5pRT commented Feb 9, 2000

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
Copy link
Author

p5pRT commented Feb 5, 2001

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.
$

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant