开发者
生科软件blast-2.13.0版本偶发线程之间互斥锁报错解决思路
生科软件blast-2.13.0版本偶发线程之间互斥锁报错解决思路
发表于2024/09/09
1.3k0

1 系统环境

OSopenEuler22.03 SP2

系统自带编译器gcc10.3.1HPCKit24.0.RC2版本毕昇编译器4.0.0

系统依赖boost1.78.0

2 blast的安装步骤

cd /path/to/blast+

wget https://ftp.ncbi.nlm.nih.gov/blast/executables/blast+/2.13.0/ncbi-blast-2.13.0+-src.tar.gz

tar xvf ncbi-blast-2.13.0+-src.tar.gz

cd ncbi-blast-2.13.0+-src

export BLAST_TOP=`pwd`

wget https://github.com/LMDB/lmdb/archive/refs/tags/LMDB_0.9.24.tar.gz

tar xvf LMDB_0.9.24.tar.gz

export LMDB_PATH=$BLAST_TOP/lmdb-LMDB_0.9.24

cd $BLAST_TOP/c++

./configure

cd ReleaseMT/build

make all_r -j40

export PATH=/path/to/blast+/ncbi-blast-2.13.0+-src/c++/ReleaseMT/bin:$PATH

3 自带编译器gcc10.3.1安装步骤

yum install gcc gcc-c++

4 HPCKit24.0.RC2版本毕昇编译器4.0.0安装步骤

参考https://www.hikunpeng.com/document/detail/zh/kunpenghpcs/hpckit/instg/KunpengHPCKit_install_012.html

5 系统依赖boost1.78.0安装步骤

yum install boost-devel

6 报错现象

运行blast程序时,偶发性出现报错:

Error: (CMutexException::eOwner) Mutex is not owned by current thread

Error: (117.2) CThread::Wrapper: CThread::Main() failed (CMutexException::eOwner) Mutex is not owned by current thread

初步判断:这个错误信息表明,程序在运行时出现了一个未捕获的异常,导致程序崩溃。具体的异常是 ncbi::CMutexException,与线程互斥锁(Mutex)相关。这个异常的提示表明,有一个线程试图释放或操作它并未拥有的互斥锁,这是不允许的行为,导致了程序的崩溃。

该程序引入了boostboost提供了多线程模块,怀疑与该模块相关。

7 定位思路

7.1 编译blast方法一

采用系统自带编译器gcc10.3.1

在执行./configure的阶段,部分打印如下图:

111.jpg

结果:未使能Boost.Thread模块

Boost.Thread Boost 库中的一个模块,用于多线程编程。它提供了跨平台的线程管理功能,允许开发者在 C++ 程序中轻松创建、管理和同步线程。Boost.Thread 作为 C++11 标准库中 std::thread 的先驱,在多线程编程中为开发者提供了强大的工具。

该编译方法生成的二进制,会偶发性出现互斥锁相关报错。

7.2 编译blast方法二

采用系统自带编译器gcc10.3.1+系统依赖boost

在执行./configure的阶段,部分打印如下图:

111.jpg

结果:成功使能Boost.Thread模块

该编译方法生成的二进制,正常运行不会偶发性出现互斥锁相关报错(经过反复测试50次)。

7.3 编译blast方法三

采用毕昇编译器4.0.0+系统依赖boost

在执行./configure的阶段,部分打印如下图:

111.jpg

结果:未使能Boost.Thread模块

该编译方法生成的二进制,会偶发性出现互斥锁相关报错。

7.4 编译blast方法四

采用毕昇编译器4.0.0+系统依赖boost

基于方法三进行定位,目的是基于毕昇编译器成功使能boost.thread模块来规避互斥锁相关报错

7.4.1 查询报错点checking for Boost.Thread… no

grep -rnl "checking for Boost.Thread"

111.jpg

打开日志ReleaseMT/status/config.log,找到checking for Boost.Thread报错点

111.jpg

这个报错是由于 std::unary_function 在现代 C++ 标准中已被移除造成的。从 C++11 开始,标准库不再推荐使用 std::unary_function std::binary_function,并且在 C++17 中它们被彻底移除。系统 Boost 版本(1.78.0)可能包含了与 std::unary_function 相关的旧代码,因此在较新的编译器中会出现这个错误(这也证明了为什么同样使用系统依赖Boost1.78.0,用系统编译器GCC10不会报错,而使用毕昇编译器4.0.0会报错)。

7.4.2 找到根因,进行规避

修改boost的一个头文件/usr/include/boost/container_hash/hash.hpp

打开头文件,定位到132行处

111.jpg

修改代码:

111.jpg

7.4.3 重新执行./configure,再次编译

重新执行./configure, 部分打印如下图,已成功使能Boost.Thread模块

111.jpg

8 追加补充

经过上述解决方法后,一次测试中仍然存在互斥锁的报错,由此可见不由Boost.Thread模块决定,继续深入分析,回到报错现象Mutex is not owned by current thread

blast代码中查询相关信息

grep -rnl "Mutex is not owned by current thread"

找到来源于文件c++/src/corelib/ncbimtx.cpp中的函数SSystemMutex::ThrowNotOwned385

111.jpg

该函数在401行调用,401行的调用条件是m_Count == 0或者m_Owner != owner

接下来,在该函数前面插桩打印定位:

std::cout << "m_Count:" << m_Count << std::endl;

std::cout << "m_Owner:" << m_Owner << std::endl;

std::cout << "owner:" << owner << std::endl;

发现,在互斥锁报错偶发时,m_Ownerowner不一致,而在此代码前的locktry lock时均已赋值过

111.jpg

但到了Unlock时这2值发生了变动,到这里已经明确了修改方案,在即将发生互斥锁报错的条件前,手动的将m_Owner=owner,这样就不会走到了ThrowNotOwned函数中,至此,重复测试300+次,已不再出现互斥锁报错。

111.jpg

收藏举报
Level 1
0
帖子
0
粉丝
0
获赞