Winapi 帮助排除一致可重复的mod_perl2/$SIG{{{uuuu DIE}错误

Winapi 帮助排除一致可重复的mod_perl2/$SIG{{{uuuu DIE}错误,winapi,mod-perl2,die,perl5.10,Winapi,Mod Perl2,Die,Perl5.10,这是Apache 2.2上的mod_perl2,ActiveState Perl 5.10 for win32 我重写$SIG{{uuuu DIE{uuuuu}并打开DBI的RaiseError标志,该标志来自文档,当数据库调用失败时,应该调用我的重写。几乎总是这样,只有一个例外,我不明白为什么 我的脚本有一个$page变量,作为mod_perl2,我可以从如下覆盖中得到: use Carp::Trace; my $full_trace = Carp::Trace::trace; $full_t

这是Apache 2.2上的mod_perl2,ActiveState Perl 5.10 for win32

我重写$SIG{{uuuu DIE{uuuuu}并打开DBI的RaiseError标志,该标志来自文档,当数据库调用失败时,应该调用我的重写。几乎总是这样,只有一个例外,我不明白为什么

我的脚本有一个$page变量,作为mod_perl2,我可以从如下覆盖中得到:

use Carp::Trace;
my $full_trace = Carp::Trace::trace;
$full_trace =~ m/^(ModPerl::ROOT::ModPerl::Registry::.*::)handler .*$/m;
my $page;
if (defined $1)
{
    eval '$page = $' . $1 . 'page';
    if (defined $page)
    {
        $json = 1 if defined $$page{json_response};
        if (defined $$page{dbh})
        {
            my $errno = $$page{dbh}->state;
            if ($errno ~~ $$page{error_handling}{allowed})
            {
                # allowed to let it go--no report, expected possible user error at some level that couldn't be caught sooner (usually db level)
                my $errmsg = $$page{error_handling}{translation_map}{$errno};
                if (defined $errmsg)
                                    {
                                               ...
这个很好用。现在,在$page中,我有一个“allowed”错误值的数组ref,当它们从DB返回时,我想对其做一些不同的处理。当DB抛出其中一个错误时,我想将其转换为用户友好的消息,$r->用JSON打印该消息,并停止执行行为a。出于某种原因,它将控制权返回到脚本行为B

以下是我脚本的主要部分:

{
    $$page{error_handling}{allowed} = ['22007'];
    $$page{json_response}{result} = $page->one_liner("select 'aa'::timestamp");
    $$page{json_response}{test} = $$page{error_handling}{state};
}
    $page->make_json; # just JSONifies $$page{json_response} and prints it
如果我注释掉第一行,我会得到一个处理意外行为C的正常错误,这是我所期望的,因为我没有将正在发生的错误添加到允许的错误列表中。真正奇怪的是,如果我剪切第一行并将其粘贴到我的$SIG{{uuuu DIE{uuuu}override中,它就工作了:JSON响应被覆盖、打印,并且在{test}被指定之前停止执行。更奇怪的是,我可以将{allowed}设置为任何一组数字,只要它特别包含“22007”,我得到了行为B。如果没有,我得到了行为C。更奇怪的是,我实际上可以用任何警告、对CORE::die的调用等填充我的重写-只要它编译,我仍然得到了行为B,即使重写不再包含任何可能的代码!此外,调用warn和CORE::die时,我没有得到任何预期的结果,只是在日志中保持沉默,因此我甚至无法尝试通过重写手动跟踪执行路径

在每次脚本保存之间,我都重新启动了Apache2.2。我甚至将覆盖移动到了与脚本本身相同的脚本文件中,超出了它通常所在的模块,并注释掉了覆盖通常所在的整个模块文件,然后重新启动

如果我去掉了第一行,或者去掉了“22007”,我就可以发出警告并死掉,或者手动调试所有我喜欢的东西,一切都按照预期进行。“22007”有什么特点,即使服务器重置,它也不会输出任何不同的内容?在整个项目中,除了翻译映射之外,其他任何地方都没有对“22007”的引用,我可以将其从该文件中完全删除并重新启动,结果也一样。它的行为就像缓存了我在当天早些时候的覆盖,永远不会忘记。这也不是浏览器缓存的问题,因为我可以添加随机查询字符串,结果也一样

这是我有过的最奇怪、最令人沮丧的现代体验,我已经没有想法了。有人有什么提示吗?我唯一能想到的是这是一个缓存问题,但我已经无数次重新启动了服务

由于这是一天的结束,我想我会尝试完全重新启动服务器计算机,但它仍然没有改变任何事情。在重新启动服务器之前,我甚至更改了{state}分配给该服务器的唯一一行:

$$page{error_handling}{state} = 'my face'; # $errno;
然而,之后的输出将{test}设为'22007',只有当我保持=$errno不变时,它才应该是这样

即使它是,比方说,它通过反向代理进行缓存,这种情况对我来说没有意义,因为请求可能不同。在完全重新启动服务器后,它如何仍然分配一个不再在代码中的值,即,在完全重新启动后,当它不再存在于任何文件中时,它如何使用我的旧$SIG{{{uuuu DIE}覆盖


更新:我还尝试将允许的错误更改为“42601”,并将db调用更改为“select”,这会产生错误代码,但没有将其添加到翻译映射中。它仍然给我行为B,将{state}设置为'42601',因此它不是特定于'22007'。放入{allowed}的任何错误代码,如果该错误实际发生,则它正在运行旧版本的覆盖。导致一个不在{allowed}中的错误并运行当前版本。但是,在到达覆盖之前,它如何知道当前错误是否在{allowed}中,或者这甚至意味着什么呢?因为覆盖是当前错误中唯一将{allowed}置为灰色的地方。

这是我的临时解决方法,但我想解决这个问题,不必在有允许错误的DB调用的任何地方添加额外的行

package MyModule::ErrorLogging;
sub InsanityWorkaround # duplicates part of $SIG{__DIE__} override for allowed errors
{
    my ($page) = @_;
    my $r = $$page{r};
    my $errno = $$page{error_handling}{state};
    if ($errno ~~ $$page{error_handling}{allowed})
    {
        # allowed to let it go--no report, expected possible user error at some level that couldn't be caught sooner (usually db level)
        my $errmsg = $$page{error_handling}{translation_map}{$errno};
        if (defined $errmsg)
        {
            use JSON::XS qw(encode_json);
            $$page{json_response} =
            {
                error => $errmsg,
            };
            my $response = encode_json($$page{json_response});
            $r->content_type("application/json");
            $r->print($response);
            exit(0);
        }
        else
        {
            return 0; # get back to script where {state} can be checked and output can be customized even further
        }
    }
    return;
}
然后我的脚本变成:

{
    $$page{error_handling}{allowed} = ['22007']; # don't be bothered by invalid timestamp error
    $$page{json_response}{result} = $page->one_liner("select 'aa'::timestamp");
    MyModule::ErrorLogging::InsanityWorkaround($page);
}
这是给行为的一种惩罚