Subject: | Leaving $@ on disconnect |
When a JDBC connection is disconnected inside an eval call,
_send_request() calls Convert::BER->encode(), which
calls eval and thereby clobbers the $@ global.
The attached patch local'izes $@ before calling $ber->encode() in
_send_request(), thus avoiding the problem.
(I first opened a bug on Convert::BER about this[1], but as Graham Barr
points out, that is not the correct place to fix it.)
Attached as well is a little script that demonstrates the problem.
I hope you can take a look at this and see if it makes sense, or if some
other way to alleviate the problem can be found.
Thanks!
Adam
[1] https://rt.cpan.org/Public/Bug/Display.html?id=78587
Subject: | jdbc_eval_clobber_fix.patch |
--- JDBC.pm.orig 2012-07-26 15:17:03.103690989 +0200
+++ JDBC.pm 2012-07-26 16:23:01.274314964 +0200
@@ -95,7 +95,8 @@
$ber->buffer("");
$h->trace_msg("Encoding [" . join(" | ", @$encode_list) . "]\n", 3)
if $debug;
- $ber->encode(@$encode_list);
+ local($@); # avoid clearing global $@ (i.e. when called in DESTROY)
+ $ber->encode(@$encode_list); # This clears $@
local($SIG{PIPE}) = "IGNORE";
$h->trace_msg("Sending request to server\n", 3) if $debug;
Subject: | jdbc_eval_clobber_example.pl |
#!/usr/bin/perl
use strict;
use warnings;
use Test::More;
eval {
my $jdbc=Simulate::DBIC->new;
die "CAUGHT\n";
};
my $error=$@;
isnt($error, '', '$@ is not empty');
is($error, "CAUGHT\n", '$@ is CAUGHT');
done_testing;
package Simulate::DBIC;
use DBI;
use DBD::JDBC;
sub new {
my ($class)=@_;
my $dsn='dbi:JDBC:hostname=HOSTNAME;port=PORT;url=jdbc:microsoft:sqlserver://SQLSERVER:PORT';
my $user='USER';
my $password='PASSWORD';
my $dbh=DBI->connect($dsn, $user, $password);
$dbh->ping;
return bless { dbh=>$dbh }, $class;
}
sub DESTROY {
my ($self)=@_;
$self->{dbh}->disconnect;
}