diff --git a/dbdimp.c b/dbdimp.c index bcb35f0c..3b278d76 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -1996,7 +1996,7 @@ static int my_login(pTHX_ SV* dbh, imp_dbh_t *imp_dbh) char* password; char* mysql_socket; int result; - int fresh = 0; + int fresh = 0; D_imp_xxh(dbh); /* TODO- resolve this so that it is set only if DBI is 1.607 */ @@ -2052,10 +2052,7 @@ static int my_login(pTHX_ SV* dbh, imp_dbh_t *imp_dbh) password, dbname, imp_dbh) ? TRUE : FALSE; if (fresh && !result) { /* Prevent leaks, but do not free in case of a reconnect. See #97625 */ - do_error(dbh, mysql_errno(imp_dbh->pmysql), - mysql_error(imp_dbh->pmysql) ,mysql_sqlstate(imp_dbh->pmysql)); Safefree(imp_dbh->pmysql); - imp_dbh->pmysql = NULL; } return result; } diff --git a/t/rt85919-fetch-lost-connection.t b/t/rt85919-fetch-lost-connection.t index 9d189ef7..5395e31a 100644 --- a/t/rt85919-fetch-lost-connection.t +++ b/t/rt85919-fetch-lost-connection.t @@ -1,44 +1,61 @@ -use strict; -use warnings; -use DBI; -use Test::More; -use lib 't', '.'; -use vars qw($table $test_dsn $test_user $test_password $mdriver); -require 'lib.pl'; - -my $dbh; -eval {$dbh= DBI->connect($test_dsn, $test_user, $test_password, - { RaiseError => 1, PrintError => 0, AutoCommit => 0 });}; -if ($@) { - plan skip_all => "ERROR: $@. Can't continue test"; -} -my $sth; -my $ok = eval { - print "Connecting...\n"; - ok( $sth = $dbh->do('SET wait_timeout = 5'), 'set wait_timeout'); - print "Sleeping...\n"; - sleep 7; - my $sql = 'SELECT 1'; - if (1) { - ok( $sth = $dbh->prepare($sql), 'prepare SQL'); - ok( $sth->execute(), 'execute SQL'); - my @res = $sth->fetchrow_array(); - is ( $res[0], undef, 'no rows returned'); - ok( $sth->finish(), 'finish'); - $sth = undef; - } - else { - print "Selecting...\n"; - my @res = $dbh->selectrow_array($sql); - } - $dbh->disconnect(); - $dbh = undef; - 1; -}; -if (not $ok) { - is ( $DBI::err, 2006, 'Received error 2006' ); - is ( $DBI::errstr, 'MySQL server has gone away', 'Received MySQL server has gone away'); - eval { $sth->finish(); } if defined $sth; - eval { $dbh->disconnect(); } if defined $dbh; -} -done_testing(); +use strict; +use warnings; +use DBI; +use Test::More; +use lib 't', '.'; +use vars qw($table $test_dsn $test_user $test_password $mdriver); +require 'lib.pl'; + +my $dbh; +eval {$dbh= DBI->connect($test_dsn, $test_user, $test_password, + { RaiseError => 1, PrintError => 0, AutoCommit => 0 });}; +if ($@) { + plan skip_all => "ERROR: $@. Can't continue test"; +} +my $sth; +my $ok = eval { + print "Connecting...\n"; + ok( $sth = $dbh->do('SET wait_timeout = 5'), 'set wait_timeout'); + print "Sleeping...\n"; + sleep 7; + my $sql = 'SELECT 1'; + if (1) { + ok( $sth = $dbh->prepare($sql), 'prepare SQL'); + ok( $sth->execute(), 'execute SQL'); + my @res = $sth->fetchrow_array(); + is ( $res[0], undef, 'no rows returned'); + ok( $sth->finish(), 'finish'); + $sth = undef; + } + else { + print "Selecting...\n"; + my @res = $dbh->selectrow_array($sql); + } + $dbh->disconnect(); + $dbh = undef; + 1; +}; +if (not $ok) { + is ( $DBI::err, 2006, 'Received error 2006' ); + is ( $DBI::errstr, 'MySQL server has gone away', 'Received MySQL server has gone away'); + eval { $sth->finish(); } if defined $sth; + eval { $dbh->disconnect(); } if defined $dbh; +} + +if (0) { + # This causes the use=after-free crash in RT #97625. + # different testcase by killing the service. which is of course + # not doable in a general testscript and highly system dependent. + system(qw(sudo service mysql start)); + use DBI; + my $dbh = DBI->connect("DBI:mysql:database=test:port=3306"); + $dbh->{mysql_auto_reconnect} = 1; # without this is works + my $select = sub { $dbh->do(q{SELECT 1}) for 1 .. 10; }; + $select->(); + system qw(sudo service mysql stop); + $select->(); + ok(1, "dbh did not crash on closed connection"); + system(qw(sudo service mysql start)); +} + +done_testing();