将python解释器嵌入静态库

问题描述

我有一个要放入静态库的函数:

run_me.h

void run_me();

run_me.cpp

namespace {
std::mutex python_mutex;
struct PythonScopedLock {
    PythonScopedLock() : _lock(python_mutex) {
        PyEval_AcquireLock();
    }

    ~PythonScopedLock() {
        PyEval_ReleaseLock();
    }

private:
    std::lock_guard<decltype(python_mutex)> _lock;
};

struct PythonInterpreter {
    PythonInterpreter() {
        Py_InitializeEx(0);
        PyEval_InitThreads();
        PyEval_ReleaseLock();
    }

    ~PythonInterpreter() {
        PyEval_AcquireLock();
        Py_Finalize();
    }
};
const PythonInterpreter python_interpreter;
} //namespace

void run_me()
{
    PythonScopedLock lock;
    // import python module and call some python code
}

接下来,在以下可执行文件中,我几乎立即在PyObject_Malloc上崩溃。

#include <tbb/tbb.h>
#include "run_me.h"
int main(){
    using namespace tbb;
    parallel_for(blocked_range<size_t>(0,1234,1),[&](const blocked_range<size_t>& r) {
        for (auto it = r.begin(); it != r.end(); ++it) {
            run_me();
        }
    });    
}

我用gdb检查了线程,它们很好地等待着锁被解锁,但是其中之一崩溃了:

  1    Thread 0x7ffff7fdb900 (LWP 21474) "tests" 0x00007ffff69374ed in __lll_lock_wait () from /lib64/libpthread.so.0
  2    Thread 0x7fffef349700 (LWP 21483) "tests" 0x00007ffff69374ed in __lll_lock_wait () from /lib64/libpthread.so.0
  3    Thread 0x7fffeef48700 (LWP 21484) "tests" 0x00007ffff69374ed in __lll_lock_wait () from /lib64/libpthread.so.0
* 4    Thread 0x7fffeeb47700 (LWP 21485) "tests" PyObject_Malloc (nbytes=41) at Objects/obmalloc.c:831
  5    Thread 0x7fffee746700 (LWP 21486) "tests" 0x00007ffff69374ed in __lll_lock_wait () from /lib64/libpthread.so.0
  6    Thread 0x7fffedf44700 (LWP 21488) "tests" 0x00007ffff69374ed in __lll_lock_wait () from /lib64/libpthread.so.0
  7    Thread 0x7fffee345700 (LWP 21487) "tests" 0x00007ffff69374ed in __lll_lock_wait () from /lib64/libpthread.so.0

当我从PythonScopedLock的主体中移出run_me并将其放入lambda主体时,情况发生了变化。这样就可以了:

#include <tbb/tbb.h>
#include "run_me.h"

namespace {
std::mutex python_mutex;
struct PythonScopedLock {
    PythonScopedLock() : _lock(python_mutex) {
        PyEval_AcquireLock();
    }

    ~PythonScopedLock() {
        PyEval_ReleaseLock();
    }

private:
    std::lock_guard<decltype(python_mutex)> _lock;
};
} // namespace 

int main(){
    using namespace tbb;
    parallel_for(blocked_range<size_t>(0,[&](const blocked_range<size_t>& r) {
        for (auto it = r.begin(); it != r.end(); ++it) {
            PythonScopedLock lock;
            run_me();
        }
    });
}

我有几个问题:

  1. 在这种情况下,在lambda内或函数主体之间加锁有什么区别?对我来说是一样的,我只想将该锁隐藏在函数主体内。
  2. 崩溃的可能原因是什么?
  3. 通过静态const PythonInterpreter python_interpreter;通过匿名命名空间中的变量进行解释程序初始化期间,除了静态初始化失败之外,还有哪些其他问题?

编辑

经过一番调试,我注意到lockrun_me定义的内部时,在静态库中,PyGILState_GetThisThreadState返回NULL。当lock在外部时,则在主线程中返回与_PyThreadState_Current相同的指针。这类问题的答案是数字1和2.。

问题3仍未解决。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...