我按照brian d foy' article on the subject中的描述覆盖CORE::GLOBAL::die
:
BEGIN {
*CORE::GLOBAL::die = sub {
say "In CORE::GLOBAL::die: [@_]";
CORE::die(@_) if $^S;
exit 1;
}
}
最终目标是将致命错误写入日志,但现在这已经足够了。让我们创建一个启用了RaiseError
的数据库句柄并执行某些操作来触发错误:
use DBI;
# Wrong password
my $dbh = DBI->connect(..., { PrintError => 0, RaiseError => 1 });
输出:
In CORE::GLOBAL::die: [DBI connect(...) failed: Access denied for user ...
到目前为止一切顺利。让我们在其上抛出一些不好的SQL:
use DBI;
my $dbh = DBI->connect(..., { PrintError => 0, RaiseError => 1 });
my $sth = $dbh->prepare('SLECT 1');
$sth->execute;
输出:
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 ...
嗯,不是我的预期(没有In CORE::GLOBAL::die
消息)。根据{{3}},当RaiseError
开启时,
任何导致错误的方法都会导致DBI有效地执行
die("$class $method failed: $DBI::errstr")
我想关键字有效,因为我希望实际调用die
来调用我的CORE::GLOBAL::die
版本。
我可以通过设置die
:
HandleError
my $dbh = DBI->connect(..., { HandleError => sub { die shift; } })
但由于RaiseError
"可用于强制错误引发异常,而不是简单地以正常方式返回错误代码,"我不明白为什么这是必要的。为什么设置RaiseError
始终导致错误调用CORE::GLOBAL::die
?难道不是使用它的全部意义吗?
答案 0 :(得分:3)
die
是Perl操作码(不是子例程)。它不能简单地被称为。 DBI和DBD模块的一部分是用C语言编写的,因此它们将无法使用die
(无需像在解决方法中那样回调Perl代码)。
但你仍然可以挂钩$SIG{__DIE__}
。就像文章所说的那样,GLOBAL::CORE::die
用于“你真的需要捕获对die
的调用”(而不是捕获异常被抛出)。