gpt4 book ai didi

mongodb - 神秘的 Moo (Perl) 错误 "Attempt to bless into a reference at..."

转载 作者:可可西里 更新时间:2023-11-01 10:11:18 37 8
gpt4 key购买 nike

可能不太可能,但我想知道以前是否有人见过这样的错误,因为我无法在生产环境之外重现它。本质上的情况是这样的:

  1. 我有一个名为 My::Budget::Module 的模块(为简单起见重命名),它负责更新应用程序中给定对象的“预算”
  2. My::Budget::Module 使用了一个名为 My::Bulk::Update::ModuleMoo 对象它执行以下操作:
    • 建立一个需要更新的数据库行数组
    • 构建一个 MySQL 更新查询字符串/语句,它会立即更新所有行
    • 实际上一次更新所有行
  3. My::Bulk::Update::Module 将执行更新并将已更新的行标记为“陈旧”,这样它们就不会被缓存

错误似乎总是发生在添加要更新的行之后但实际应用更新的代码返回之前的某处。

如果您查看我在下面包含的堆栈跟踪,您可以看到错误采用以下形式

Attempt to bless into a reference at...

发生这种情况的点是 Moo/Object.pm 的构造函数,它是 MooVersion 2.003002 来自 cpan(参见 here)。

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::CollectionMoo::Object 被实例化,第一个参数是 My::Bulk::更新::模块=HASH(0xf784b50)。考虑到应用程序逻辑,我认为 MongoDB::Collection 不应在此处实例化,也不应将 My::Bulk::Update::Module 传递给 MongoDB: :Collection 完全没有。

除了它是一个 Moo 对象之外,My::Bulk::Update::Module 不扩展任何其他模块并且被设计成一个独立的“实用程序”模块。它在整个应用程序中仅在一个地方使用。

有没有人以前见过类似的东西?

编辑: 添加更多代码 - apply_bulk_update 根本没有做太多事情。这里没有对 MongoDB::Collection 的调用,MongoDB::Collection 只是“碰巧”成为这个特定示例中堆栈跟踪中包含的模块。这并不总是 MongoDB::Collection - 我还看到了 MongoDB::TimestampMongoDB::CursorSearch: :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 时立即终止,有时会在调用 _generate_query 时终止,有时会在最后一行执行查询后...

最佳答案

以防万一有人感兴趣...

在进一步调试之后,错误被追踪到 My::Bulk::Update::Module::apply_bulk_updateMy::Bulk::Update: :Module::_generate_query 被调用,但记录这些子例程中的代码确定它们没有按预期执行。

为了确定发生了什么,B::Deparse 用于重建这些子程序主体的源代码(或者至少是位于这些子程序所在内存地址的源代码)指点)

在使用这个库之后,例如

B::Deparse->new->coderef2text(\&My::Bulk::Update::_generate_query)

My::Bulk::Update::_generate_query 指向包含完全不同的内容(即 MongoDB::Collection::新的等)。

这个问题似乎已经通过 Sub::Defer 模块(它是 Moo 的依赖项)中的以下提交在上游解决了。

https://github.com/moose/Sub-Quote/commit/4a38f034366e79b76d29fec903d8e8d02ee01896

如果您阅读提交摘要,您可以看到所做的更改:

Prevent defer_info and undefer_sub from operating on expired subs. Validate that the arguments to defer_info and undefer_sub refer to actual live subs. Use the weak refs we are storing to the deferred and undeferred subs to make sure the original subs are still alive, and we aren't returning data related to a reused memory address. Also make sure we don't expire data related to unnamed subs. Since the user can capture the undeferred sub via undefer_sub, we can't track the expiry without using a fieldhash. For now, avoid introducing that complexity, since the amount we leak should not be that great.

升级 Sub::Defer 的版本似乎已经解决了这个问题。

关于mongodb - 神秘的 Moo (Perl) 错误 "Attempt to bless into a reference at...",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49727740/

37 8 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com