LSF API的lsb_submit是否线程安全?多线程调用异常求助
关于LSF集群lsb_submit API线程安全性的问题
我的应用尝试通过3个线程并发调用lsb_submit向LSF集群提交作业,调用时进程要么因段错误终止,要么打印如下提示:
Conflict parameter LSB_SUB_PROJECT_NAME - Ignored. Conflict parameter LSB_SUB_JOB_DESCRIPTION - Ignored. Conflict parameter LSB_SUB_USER_GROUP - Ignored. Conflict parameter LM_PROJECT - Ignored.
但在单线程中顺序调用lsb_submit时,作业提交可成功完成。
请问:
lsb_submit是否非线程安全?- 有没有办法让该API实现线程安全?
- 是否存在线程安全版本?
以下是复现问题的最小化代码:
int func() { struct submit req; memset(&req, 0, sizeof(req)); struct submitReply reply; for (int i = 0; i < LSF_RLIM_NLIMITS; i++) { req.rLimits[i] = DEFAULT_RLIMIT; } req.options = 0; req.options2 = 0; req.beginTime = 0; req.termTime = 0; req.numProcessors = 1; req.maxNumProcessors = 1; std::string cmd = "ls"; req.command = new char[cmd.size()+1]; cmd.copy(req.command, cmd.size()); req.command[cmd.size()] = '\0'; int jobId = lsb_submit(&req, &reply); if (jobId < 0) { std::cout << "\nFailed submit "; /*handle*/ } else { std::cout << "\nSuccess submit "; } return 1; } int main(int argc, char **argv) { if (lsb_init(argv[0]) < 0) { lsb_perror(NULL); exit(-1); } std::vector<std::future<int>> vec; for (int i=0; i<2; ++i) { vec.push_back(std::async(std::launch::async, func)); } std::cout << "\nOutput = " << vec[0].get(); std::cout << "\nOutput = " << vec[1].get(); }
每次运行程序的输出结果不同:
- 有时会出现段错误:
$ ./a.out ls *** Error in `./a.out': double free or corruption (fasttop): 0x00002ae760006440 *** ======= Backtrace: ========= /lib64/libc.so.6(+0x81329)[0x2ae75a024329] <>/lib/liblsf.so(+0x15253b)[0x2ae75910a53b] <>/lib/liblsf.so(+0x152a9a)[0x2ae75910aa9a] <>/lib/liblsf.so(callLimVarXdrSize_+0x650)[0x2ae75910bb70] <>/lib/liblsf.so(callLim_+0x27)[0x2ae75910d417] <>/lib/liblsf.so(+0x146e4a)[0x2ae7590fee4a] <>/lib/liblsf.so(ls_getmastername+0x69)[0x2ae7590ff079] <>/lib/libbat.so(getMasterName+0x170)[0x2ae758cae260] <>/lib/libbat.so(+0xa5500)[0x2ae758c17500] <>/lib/libbat.so(lsb_submit+0xeb)[0x2ae758c1b7eb] ./a.out[0x4036a3] ...
- 有时会出现参数冲突提示但作业提交成功:
$ ./a.out ls Aug 7 10:36:27 2024 32345 4 10.1 Conflict parameter LSB_SUB_PROJECT_NAME - Ignored. Aug 7 10:36:27 2024 32345 4 10.1 Conflict parameter LSB_SUB_JOB_DESCRIPTION - Ignored. Aug 7 10:36:27 2024 32345 4 10.1 Conflict parameter LM_PROJECT - Ignored. Aug 7 10:36:27 2024 32345 4 10.1 Conflict parameter JOB_DESCRIPTION - Ignored. Res = Job <480466> is submitted to default queue <>. Success submit 1 Res = Job <480467> is submitted to default queue <>. Success submit 1
回答
lsb_submit确实是非线程安全的
从你遇到的段错误(double free/corruption)和参数冲突提示就能看出——这些都是多线程环境下共享资源竞争导致的典型问题。LSF的经典C API(包括lsb_submit)内部使用了全局状态变量,并发调用时会出现线程间的资源覆盖,从而引发内存错误或参数解析冲突。实现线程安全的可行方案
- 全局互斥锁:在所有线程调用
lsb_submit前后加一把全局互斥锁,确保同一时间只有一个线程执行该API调用。示例代码如下:
#include <mutex> std::mutex lsf_submit_mutex; int func() { // ... 原有req初始化代码 ... std::lock_guard<std::mutex> lock(lsf_submit_mutex); int jobId = lsb_submit(&req, &reply); // ... 后续处理代码 ... }
这种方式简单直接,但会牺牲并发性能,所有提交请求会变成串行执行。
每个线程独立初始化LSF环境:部分LSF版本支持线程级别的环境初始化,你可以尝试在每个线程内调用
lsb_init(而非主线程一次性初始化)。不过需要验证你的LSF版本是否支持这种用法,有些旧版本不支持线程级隔离。改用进程替代线程:如果性能要求允许,可以用多进程替代多线程提交作业,每个进程独立调用
lsb_submit,完全避免线程间的资源竞争问题。
- 是否存在线程安全版本
LSF的新版本提供了REST API(通过LSF Web Service),这是天然线程安全的,因为每个请求都是独立的HTTP调用,没有共享的全局状态。如果你的集群支持LSF Web Service,可以考虑改用REST API来实现并发提交。
另外,IBM官方文档明确说明:传统的LSF C API(包括lsb_submit)不保证线程安全性,并发调用需要用户自行处理同步。
内容的提问来源于stack exchange,提问作者bdd
相关产品推荐
相关产品推荐

