可能是一个很长的镜头,但我想知道是否有人之前看到过这样的错误,因为我无法在生产环境之外重现它。基本上情况如下:
My::Budget::Module
的模块(为简单而重命名),负责更新"预算"对于应用程序中的给定对象My::Budget::Module
使用我构建的名为Moo
的{{1}}对象执行以下操作:
My::Bulk::Update::Module
将执行更新,并将已更新的行标记为"陈旧"这样他们就不会被缓存在添加要更新的行之后但在实际应用更新的代码返回之前,似乎总是会出现错误。
如果查看下面包含的堆栈跟踪,可以看到错误采用
形式 My::Bulk::Update::Module
并且发生这种情况的点在Attempt to bless into a reference at...
的构造函数中,Moo/Object.pm
Version 2.003002
来自Moo
(参见here)。
cpan
向后移动堆栈跟踪会导致Attempt to bless into a reference at /path/to/module/from/cpan/Moo/Object.pm line 25 at /path/to/module/from/cpan/Moo/Object.pm line 25.
Moo::Object::new(My::Bulk::Update::Module=HASH(0xf784b50)) called at (eval 1808) line 28
MongoDB::Collection::new(My::Bulk::Update::Module=HASH(0xf784b50)) called at /path/to/my/bulk/update/module line XXXX
My::Bulk::Update::Module::apply_bulk_update(My::Bulk::Update::Module=HASH(0xf784b50)) called at /path/to/my/budget/module line XXXX
My::Budget::Module::update_budget(My::Budget::Module=HASH(0xf699a38)) called at /path/to/my/budget/module line XXXX
&事情开始变得非常奇怪。
MongoDB::Collection
也是MongoDB::Collection
模块,但此时出现的模块各不相同,除了它始终是cpan
对象外,我无法在此处看到模式。此外,我不确定为什么要对这个模块进行实例化,因为在提到的行中没有调用Moo
。
此外,从堆栈跟踪看起来MongoDB::Collection::new
和MongoDB::Collection
实例化,第一个参数为Moo::Object
。鉴于应用程序逻辑,我不认为My::Bulk::Update::Module=HASH(0xf784b50)
应该在这里实例化,也不应该MongoDB::Collection
传递给My::Bulk::Update::Module
。
除了MongoDB::Collection
对象之外,Moo
不扩展任何其他模块,并且设计为独立的"实用程序"模块。它仅用于整个应用程序中的一个位置。
有没有人见过类似的东西?
编辑:添加更多代码 - My::Bulk::Update::Module
根本不做任何事情。此处没有apply_bulk_update
来电,而MongoDB::Collection
只是"发生"在这个特定的例子中,它是包含在堆栈跟踪中的moudule。这并不总是MongoDB::Collection
- 我还看到MongoDB::Collection
,MongoDB::Timestamp
,MongoDB::Cursor
,Search::Elasticsearch::Serializer::JSON
等等
Search::Elasticsearch::Logger::LogAny
代码有时会在调用sub apply_bulk_update
{
my $self = shift;
my ($db) = @_; # wrapper around DBI module
my $query = $self->_generate_query(); # string UPDATE table SET...
my $params = $self->_params; # arrayref
return undef unless $params && scalar @$params;
$db->do($query, undef, @$params);
}
时死亡,有时在调用apply_bulk_update
时有时会死,有时在最后一行执行查询后...
答案 0 :(得分:2)
万一有人对此感兴趣......
经过一段时间的进一步调试后,错误被追溯到调用My::Bulk::Update::Module::apply_bulk_update
或My::Bulk::Update::Module::_generate_query
的确切位置,但这些子程序中的日志代码确定它们没有按预期执行。
确定B::Deparse
上发生了什么用于重建这些子程序主体的源代码(或者至少是位于这些子指向的内存地址的源代码)
使用此库后,例如
B::Deparse->new->coderef2text(\&My::Bulk::Update::_generate_query)
很明显,当My::Bulk::Update::_generate_query
指向包含完全不同的内存位置(即MongoDB::Collection::new
等)时发生错误。
此问题似乎已通过Sub::Defer
模块中的以下提交(它是Moo
的依赖项)在上游解决。
https://github.com/moose/Sub-Quote/commit/4a38f034366e79b76d29fec903d8e8d02ee01896
如果您阅读了提交摘要,则可以看到所做的更改:
防止defer_info和undefer_sub对expired subs进行操作。验证defer_info和undefer_sub的参数是否参考 实际的潜艇使用我们存储的弱引用到延迟和 未确定的潜艇,以确保原来的潜艇仍然活着,我们 没有返回与重用内存地址相关的数据。还要确保我们不会过期与未命名的潜艇相关的数据。自从 用户可以通过undefer_sub捕获未使用的子,我们无法跟踪 到期而不使用fieldhash。现在,避免引入它 复杂性,因为我们泄漏的数量不应该那么大。
升级Sub::Defer
版本似乎解决了这个问题。