Question

I overrode CORE::GLOBAL::die as described in brian d foy's article on the subject:

BEGIN {
    *CORE::GLOBAL::die = sub {
        say "In CORE::GLOBAL::die: [@_]";
        CORE::die(@_) if $^S;
        exit 1;
    }
}

The ultimate goal is to write fatal errors to a log, but this is good enough for now. Let's create a database handle with RaiseError turned on and do something to trigger an error:

use DBI;

# Wrong password
my $dbh = DBI->connect(..., { PrintError => 0, RaiseError => 1 });

Outputs:

In CORE::GLOBAL::die: [DBI connect(...) failed: Access denied for user ...

So far so good. Let's throw some bad SQL at it instead:

use DBI;

my $dbh = DBI->connect(..., { PrintError => 0, RaiseError => 1 });
my $sth = $dbh->prepare('SLECT 1');
$sth->execute;

Outputs:

DBD::mysql::st execute failed: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'SLECT 1' at line 1 at ...

Hmmm, not what I expected (there's no In CORE::GLOBAL::die message). According to the docs, when RaiseError is on,

any method which results in an error will cause the DBI to effectively do a die("$class $method failed: $DBI::errstr")

I guess the key word is effectively, since I would expect an actual call to die to invoke my version of CORE::GLOBAL::die.

I can force all errors to die by setting HandleError:

my $dbh = DBI->connect(..., { HandleError => sub { die shift; } })

But since RaiseError "can be used to force errors to raise exceptions rather than simply return error codes in the normal way," I don't understand why this is necessary. Why doesn't setting RaiseError always result in a call to CORE::GLOBAL::die on error? Isn't that the whole point of using it?

Was it helpful?

Solution

die is a Perl opcode (not a subroutine). It can't simply be called. Parts of DBI and DBD modules are written in C, so they wouldn't be able to use die (without calling back into Perl code as in your workaround).

You can still hook $SIG{__DIE__}, though. Like the article says, GLOBAL::CORE::die is for when "you really need to catch calls to die" (as opposed to catching exceptions being thrown).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top