Perl — сценарий многопоточности печатает карту памяти и backtrace

Вопрос:

enter image description here Когда я вызываю свой многопоточный скрипт perl, в несколько случаев он выдает некоторое исключение, подобное следующему. Мне жаль, что я не мог использовать код. Но если это действительно необходимо, я могу попытаться создать фрагмент (если это действительно необходимо). Потому что я предполагаю, что это должно иметь некоторый теоретический ответ.

*** 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; использовать threads :: shared; Пожалуйста, дайте мне знать ваши взгляды.

Ниже приведены сведения о версии библиотек потоков.

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

Лучший ответ:

Чтобы дать вам твердый ответ, нам нужно что-то, что мы можем запустить и устранить. В противном случае ошибка не воспроизводится.

Сказав это — это похоже на нечто похожее на то, с чем я столкнулся раньше, когда определенные модули не являются потокобезопасными — они будут часто работать нормально, а затем очень иногда взрываются в вашем лице.

Например, Crypt :: SSLeay еще в 2008 году. Net :: SSLeay до 1.4.2

Общее обходное решение — прекратить загрузку виновных во время компиляции с use — потому что тогда одно и то же состояние наследуется всеми потоками, а вместо этого в потоке загружает их во время выполнения с require и import. Делая это, вы их изолируете — ваши потоки займут немного больше времени, но вы не должны спамить нити в любом случае.

Или используйте другой модуль, который является потокобезопасным.

С вашим обновлением и скриншотом — Net::SSH2 упоминается — и это означает, что один из ваших других модулей тянет это.

Однако Net :: SSH thread safey указывает, что libssh может иметь некоторые ограничения на безопасность потоков:

Потоковая безопасность: просто не обменивайтесь ручками одновременно

Вы явно не упоминаете его использование, но похоже, что он втягивается другим модулем. По предположению, это будет Net::Netconf::Manager.

И, как вторая догадка, вполне возможно, что это «общие дескрипторы», потому что они не понимают, что они выполняются в потоке.

Таким образом, этот модуль является тем, который я бы предложил изолировать внутри потоков:

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

И создайте экземпляр внутри потока.

Поскольку вы используете модель рабочих потоков, это должно быть минимальным накладным расходами и будет означать, что вы не сталкиваетесь с этой проблемой.

Но в более общем плане — неразумно предполагать, что модули являются потокобезопасными, если они явно не говорят, что они есть. Главные пункты «отключения» обычно возникают, когда любой вид совместного использования ресурсов может предполагаться/подразумеваться модулем, например, сетевыми сокетами, файловыми дескрипторами, подключениями к базам данных и т.д. Часто сокет создается при создании экземпляра (например, точка, в которой вы передаете имя пользователя /password) и наличие двух потоков, пытающихся одновременно подключить сокет, — это потенциальное состояние гонки.

Оцените статью
TechArks.Ru
Добавить комментарий