Skip Menu |

This queue is for tickets about the DBD-mysql CPAN distribution.

Report information
The Basics
Id: 46085
Status: resolved
Priority: 0/
Queue: DBD-mysql

People
Owner: Nobody in particular
Requestors: doug.fischer [...] grantstreet.com
Cc:
AdminCc:

Bug Information
Severity: Normal
Broken in: 4.011
Fixed in: (no value)



Subject: DBD::mysql auto-reconnect does not set Active flag
This bug has been cross-posted to the MySQL bug database as ticket #44883. In cases in which auto-reconnect is enabled for a connection (this is especially true under mod_perl where auto-reconnect is automatically turned on by default), performing a disconnect on the DB handle and then subsequently performing a database operation on that handle (resulting in the automatic reconnection of the handle), the Active flag is not reset to 1, but is "", as set by the disconnect operation. Code that inspects this flag to determine if the connection is indeed active is misled. Subsequent disconnect attempts on this reconnected handle will also fail, as disconnect() inspects the Active flag. To replicate, perform an operation like the following, either under mod_perl or with an explicit setting of auto-reconnect: $dbh = DBI->connect(...); # gets mysql thread ID 123 and sets $dbh->{Active} to 1 $dbh->disconnect; # Actually disconnects from the DB and sets $dbh->{Active} to "" $dbh->do("SELECT 1"); # *Does not complain!*. Automatically reconnects to DB with mysql thread ID 124 (or next available) BUT leaves $dbh->{Active} as "". $dbh->disconnect; # Does nothing; Does not actually disconnect mysql thread ID 124 because Active is "" Attached file includes code patch that simply duplicates the one line of code from dbd_db_login() that sets the Active flag to mysql_db_reconnect(), as well as a test to ensure that this condition is corrected. While it could be argued that an explicit disconnect() should not have a subsequent implicit reconnect, there are some valid instances in which this may occur (forking of children that are passed an active database handle). So long as DBD::mysql allows such a thing to be done, it should handle it the right way.
Subject: DBD-mysql-4.011-reconnect_active_flag.patch
diff -PurN DBD-mysql-4.011.orig/dbdimp.c DBD-mysql-4.011/dbdimp.c --- DBD-mysql-4.011.orig/dbdimp.c 2009-04-13 08:39:38.000000000 -0400 +++ DBD-mysql-4.011/dbdimp.c 2009-05-07 13:19:37.000000000 -0400 @@ -4420,6 +4420,12 @@ ++imp_dbh->stats.auto_reconnects_failed; return FALSE; } + + /* + * Tell DBI, that dbh->disconnect should be called for this handle + */ + DBIc_ACTIVE_on(imp_dbh); + ++imp_dbh->stats.auto_reconnects_ok; return TRUE; } diff -PurN DBD-mysql-4.011.orig/MANIFEST DBD-mysql-4.011/MANIFEST --- DBD-mysql-4.011.orig/MANIFEST 2009-04-13 12:00:46.000000000 -0400 +++ DBD-mysql-4.011/MANIFEST 2009-05-07 13:19:37.000000000 -0400 @@ -17,6 +17,7 @@ eg/proc_example3.pl t/00base.t t/10connect.t +t/15reconnect.t t/20createdrop.t t/25lockunlock.t t/29warnings.t diff -PurN DBD-mysql-4.011.orig/t/15reconnect.t DBD-mysql-4.011/t/15reconnect.t --- DBD-mysql-4.011.orig/t/15reconnect.t 1969-12-31 19:00:00.000000000 -0500 +++ DBD-mysql-4.011/t/15reconnect.t 2009-05-07 13:20:53.000000000 -0400 @@ -0,0 +1,39 @@ +#!perl -w +# vim: ft=perl + +use Test::More; +use DBI; +use DBI::Const::GetInfoType; +use strict; +$|= 1; + +use vars qw($test_dsn $test_user $test_password); +use lib 't', '.'; +require 'lib.pl'; + +my $dbh; +eval {$dbh= DBI->connect($test_dsn, $test_user, $test_password, + { RaiseError => 1, PrintError => 1, AutoCommit => 0 });}; + +if ($@) { + plan skip_all => "ERROR: $DBI::errstr. Can't continue test"; +} +plan tests => 8; + +ok(defined $dbh, "Connected to database"); + +ok($dbh->{Active}, "checking for active handle"); + +ok($dbh->{mysql_auto_reconnect} = 1, "enabling reconnect"); + +ok($dbh->{AutoCommit} = 1, "enabling autocommit"); + +ok($dbh->disconnect(), "disconnecting active handle"); + +ok(!$dbh->{Active}, "checking for inactive handle"); + +ok($dbh->do("SELECT 1"), "implicitly reconnecting handle with 'do'"); + +ok($dbh->{Active}, "checking for reactivated handle"); + +$dbh->disconnect();
Hi, Thanks for this patch! I will be making a release, 4.012, that will include your patch! --Patrick On Thu May 14 14:45:31 2009, DKF wrote: Show quoted text
> This bug has been cross-posted to the MySQL bug database as ticket > #44883. > > In cases in which auto-reconnect is enabled for a connection (this is > especially true > under mod_perl where auto-reconnect is automatically turned on by > default), performing a > disconnect on the DB handle and then subsequently performing a > database operation on that > handle (resulting in the automatic reconnection of the handle), the > Active flag is not > reset to 1, but is "", as set by the disconnect operation. Code that > inspects this flag to > determine if the connection is indeed active is misled. Subsequent > disconnect attempts on > this reconnected handle will also fail, as disconnect() inspects the > Active flag. > > To replicate, perform an operation like the following, either under > mod_perl or with an > explicit setting of auto-reconnect: > > $dbh = DBI->connect(...); # gets mysql thread ID 123 and sets $dbh-
> >{Active} to 1
> $dbh->disconnect; # Actually disconnects from the DB and sets $dbh-
> >{Active} to ""
> $dbh->do("SELECT 1"); # *Does not complain!*. Automatically reconnects > to DB with mysql > thread ID 124 (or next available) BUT leaves $dbh->{Active} as "". > $dbh->disconnect; # Does nothing; Does not actually disconnect mysql > thread ID 124 > because Active is "" > > Attached file includes code patch that simply duplicates the one line > of code from > dbd_db_login() that sets the Active flag to mysql_db_reconnect(), as > well as a test to > ensure that this condition is corrected. > > While it could be argued that an explicit disconnect() should not have > a subsequent > implicit reconnect, there are some valid instances in which this may > occur (forking of > children that are passed an active database handle). So long as > DBD::mysql allows such a > thing to be done, it should handle it the right way.
see previous comment.