Skip to content

Perl crashes when used with DBIx::Connector #210

@bit0mike

Description

@bit0mike

This is the same issue as ap/DBIx-Connector#50 as it's not clear which module is causing the problem.

Trying to use DBD::MariaDB in place of DBD::mysql results in some weird behavior sometimes, notably Perl crashing (SIGBUS core dump, on FreeBSD at least) when disconnecting from the database when mixed with Parallel::ForkManager. Obviously normally Parallel::ForkManager shouldn't be used with open DBI handles, but that's one of the things DBIx::Connector is supposed to make "safe". And with the DBD::mysql driver, it is.

DBIx::Connector in its release version does not have a specific driver for MariaDB. In the master branch, there is a basic one that is more or less a duplicate of the mysql one. Using it doesn't fix the problem.

Script to reproduce:

#!/usr/local/bin/perl
use v5.38;
use Parallel::ForkManager;
use File::Temp;
use DBIx::Connector;
my $user = 'REDACTED';
my $pass = 'REDACTED';
my $forkmgr = Parallel::ForkManager->new( 32, File::Temp->newdir() );
my $dbix_obj = DBIx::Connector->new(
"DBI:MariaDB:database=test;host=localhost;mariadb_connect_timeout=10", $user, $pass, # dumps core sometimes
#"DBI:mysql:database=test;host=localhost;mysql_connect_timeout=10", $user, $pass, # does not dump core ever
{ AutoCommit => 1, RaiseError => 1, ShowErrorStatement => 1, Callbacks => {} }
);
$dbix_obj->mode('fixup');
$dbix_obj->dbh; # Comment out to stop core dumps with DBD::MariaDB
foreach my $c ( 0 .. 5000 ) {
unless ( $forkmgr->start ) {
my ($q) = $dbix_obj->run( fixup => sub { $_->selectall_array( 'SELECT MD5(?)', undef, $c ) } );
say "pid=$$ c=$c result=$$q[0]";
$forkmgr->finish(0);
}
}
$forkmgr->wait_all_children;

On FreeBSD 14.1 this code will create MANY coredumps, all apparently when the child process DB handles try to disconnect. The code does run successfully anyway (but obviously slowly because of all the core files being written) because the crash is when the child is trying to exit anyway.

On Ubuntu 24.04 this code instead prints this at every DB disconnect -- but not every time the program runs, just sometimes:

panic: DBI active kids (-1) < 0 or > kids (0) at /usr/lib/x86_64-linux-gnu/perl5/5.38/DBI.pm line 759.

To stop that warning (Ubuntu) or coredumps (FreeBSD) any one of the following works:

use DBD::mysql (version 4.x; 5.x doesn't work w/ MariaDB anymore) instead of DBD::MariaDB. I don't know why there'd be a difference between the two, but, there is. This is why I went down the path of adding DBIx::Connector::Driver::MariaDB in the first place, to see if it would help. It did not, but it's good to have anyway.

OR

move DBIx::Connector->new inside the $forkmgr->start block, which I know is more "correct" to do (forking with open handles of ANY kind is bad, after all), but making it fork-safe outside the block is one of the whole points of using DBIx::Connector in the first place

OR

remove the $dbix_obj->dbh call immediately after connecting. I was doing this to make sure it could really connect, vs trying to do it lazily later on -- if the DB is really truly down, I want to know up front instead of later on. There could be a better way of accomplishing this test though (ping?), if this is a seriously stupid thing for me to be doing this way, I'm open to suggestions

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions