【问题标题】:Perl - Multithreading script prints memory map and backtracePerl - 多线程脚本打印内存映射和回溯
【发布时间】:2018-04-14 22:20:14
【问题描述】:

当我调用我的多线程 perl 脚本时,在少数情况下,它会抛出一些类似于以下内容的异常。很抱歉我无法共享代码。但如果真的需要,我可以尝试构建一个 sn-p(如果真的需要)。因为我想这应该有一些理论上的答案。

*** glibc detected *** perl: double free or corruption (!prev): 0x00007f775401e9a0 ***
======= Backtrace: =========
/lib64/libc.so.6[0x3d74c75e66]
/lib64/libc.so.6[0x3d74c789b3]
/lib64/libc.so.6[0x3d74c7b880]
/lib64/libc.so.6(realloc+0xe5)[0x3d74c7baf5]
/usr/lib/../lib64/libcrypto.so.10(CRYPTO_realloc+0x5f)[0x7f775907bd8f]
/usr/lib/../lib64/libcrypto.so.10(lh_insert+0xee)[0x7f77590f763e]
/usr/lib/../lib64/libcrypto.so.10(OBJ_NAME_add+0x6b)[0x7f775907f12b]
/usr/lib/../lib64/libcrypto.so.10(EVP_add_cipher+0x27)[0x7f7759102387]
/usr/lib/../lib64/libcrypto.so.10(OpenSSL_add_all_ciphers+0x4b7)[0x7f7759106a07]
/usr/lib/../lib64/libcrypto.so.10(OPENSSL_add_all_algorithms_noconf+0xe)[0x7f775910653e]
/usr/local/lib/libssh2.so.1(libssh2_init+0x39)[0x7f77596800b9]

为什么会出现这样的错误?

我正在使用 Thread::Queue;使用线程::共享;请让我知道您的看法。

以下是线程库版本信息。

use threads; - installed v2.15 (latest - 2.16)
use Thread::Queue; - installed v3.12 (up to date)
use threads::shared; - installed v1.56 (latest - 1.57)
perl - installed v5.26.1

其他库有::

use YAML::XS 'LoadFile';  - 0.66 up to date
use Net::Netconf::Manager; - 1.02 up to date
use Config::Properties; - 1.80 up to date
use Sys::Syslog; - 0.35 up to date
use DateTime::Format::Strptime; - 1.74 up to date
use DateTime; - 1.44 up to date
use XML::LibXML; - 2.0129 (latest 2.0139)
use Regexp::Common qw/net/; - 2017060201 up to date
use Getopt::Long; - 2.5 up to date

【问题讨论】:

  • 我们至少需要知道您正在使用哪些其他库(包括版本和 perl 版本)。但是如果没有一段可重现的代码,我们就无法可靠地回答。
  • 你的截图提到Net::SSH2:About Net::SSH2 thread safety

标签: multithreading perl memory-management scripting threadpool


【解决方案1】:

为了给您一个明确的答案,我们需要一些可以运行和排除故障的东西。否则错误是不可重现的。

话虽如此 - 这看起来类似于我之前遇到的某些模块不是线程安全的情况 - 它们通常会运行良好,然后偶尔会在你的脸上爆炸。

例如Crypt::SSLeay 回到 2008 年。Net::SSLeay 1.4.2 之前的版本

一般的解决方法是 stop 在编译时使用 use 加载罪魁祸首 - 因为所有线程都继承相同的状态 - 而不是 线程中,在运行时使用requireimport 加载它们。通过这样做,您将它们隔离 - 您的线程将花费 稍微 更长的时间来启动,但无论如何您都不应该在 perl 中发送垃圾邮件。

或者使用其他线程安全的模块。

随着您的更新和屏幕截图 - 提到了 Net::SSH2 - 这意味着您的其他模块之一正在将其引入。

但是Net::SSH thread safey 表示libssh 可能对线程安全有一些限制:

线程安全:只是不要同时共享句柄

你没有明确提到使用它,但它看起来像是被另一个模块拉进来的。猜测是Net::Netconf::Manager

作为第二个进一步的猜测 - 它很可能正在执行“共享句柄”,因为它没有意识到它正在线程中运行。

所以这个模块是我建议在线程中隔离的模块:

require 'Net::NetConf::Manager';
Net::NetConf::Manager -> import; 

并在线程内进行实例化。

当您使用工作线程模型时,这应该是最小的开销,并且意味着您不会遇到这个问题。

但更一般地说 - 假设模块是线程安全的是不明智的,除非它们明确表示它们是线程安全的。主要的“绊脚石”点通常是模块可以假设/暗示任何类型的资源共享,例如网络套接字、文件句柄、数据库连接等。通常在实例化时创建套接字(例如,您传递用户名的点/password) 并且有两个线程试图同时驱动一个套接字是一个潜在的竞争条件。

【讨论】:

  • 谢谢。我已将我正在使用的所有软件包及其版本信息添加到我的问题中。我没有使用您在回答中提到的任何软件包。你是对的,这个错误偶尔会爆发。我真的很担心是什么导致了这个问题!
  • 你能得出什么结论吗?
  • 从模块列表中,小于错误的屏幕截图,表明您遇到问题的是libssh。而Net::Netconf::ManagerNet::SSH2 作为Net::Netconf::Access::ssh 的一部分引入,这是关于线程安全的书面警告。 (任何没有提到线程安全的模块,都认为它是线程安全的是不明智的——Net::Netconf::Manager 属于这一类。)
  • 非常感谢!我正在测试 Net::Netconf::Manager 模块的隔离性,但我没有做对:(。我的线程调用带有参数的子例程。我试图将您在上面发布的行放在参数下方子程序中的赋值,但它没有按预期工作。你能帮忙吗?
  • 您可以回答吗?谢谢。
猜你喜欢
  • 2018-05-24
  • 1970-01-01
  • 1970-01-01
  • 2018-05-18
  • 1970-01-01
  • 2016-09-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多