简体   繁体   English

如何为在 C++ 应用程序中使用 embed python 创建的新线程状态获取 GIL

[英]How to acquire GIL for the new thread state created using embed python in C++ application

I have a C++ application where we provide a python editor(which uses python 3.7), users can input and execute the python code in the editor.我有一个 C++ 应用程序,我们提供了一个 python 编辑器(使用 python 3.7),用户可以在编辑器中输入和执行 python 代码。 Following is the sample code where we are creating a new thread state and making it current before executing the script provided by users.以下是我们在执行用户提供的脚本之前创建新线程状态并使其成为当前状态的示例代码。

#include <python.h>

PyThreadState* globalthread;

void executescript()
{
    PyEval_SaveThread();
    PyThreadState* ts = PyThreadState_New(globalthread->interp);
    int gilstate = PyGILState_Check(); //check whether GIL is with current thread or not
    if (!gilstate)
    {
        PyEval_RestoreThread(ts);
    }
    else
    {
        
        PyThreadState_Swap(ts);
    }
    // get the thread state with which GIL is currently assigned
    PyThreadState * gilthreadstate = PyGILState_GetThisThreadState(); 
    //----> the above line return pointer to global thread state (gilthreadstate == globalthread)
    //----> which means the GIL is not acquired by the new current thread
    gilstate = PyGILState_Check(); //results in zero as GIL is not with current thread
    std::string str = "def script():\n\timport sys\n\tsys.path.append('C:\\Python\\Python37\\Lib\\site-packages')\n\tprint(sys.path)\n\timport numpy\n\tarr = numpy.array([1, 2, 3, 4, 5])\n\tprint(arr)\nscript()";
    PyRun_SimpleString(str.c_str());
    PyThreadState_Clear(ts);
    PyThreadState_DeleteCurrent();
    PyEval_RestoreThread(globalthread);
    //following stmt returns 1 as the current thread is global thread and it has GIL with it
    gilstate = PyGILState_Check(); 
}

int main()
{
    Py_Initialize();
    PyEval_InitThreads();
    globalthread = PyThreadState_Get();
    executescript();
    PyThreadState_Swap(globalthread);
    Py_FinalizeEx();
    return 0;
} 

The new current thread is not acquiring the GIL when PyEval_RestoreThread or PyThreadState_Swap is called on it.当 PyEval_RestoreThread 或 PyThreadState_Swap 被调用时,新的当前线程不会获取 GIL。 Python scripts having import numpy or import pandas will end in deadlock due to this.因此,具有import numpyimport pandas Python 脚本将以死锁告终。 Can someone let me know how to acquire GIL for the new thread state or where the code is wrong?有人可以让我知道如何为新线程状态或代码错误获取 GIL 吗?

Comment by hn-1-8e9-wheres-my-share-m has resolved the issue by creating a new C++ thread. hn-1-8e9-wheres-my-share-m的评论通过创建一个新的 C++ 线程解决了这个问题。 Here is my modified code.这是我修改后的代码。

#include <python.h>
#include <thread>
PyThreadState* globalthread;

void execute()
{
    PyThreadState* ts = PyThreadState_New(globalthread->interp);

    int gilstate = PyGILState_Check();
    if (!gilstate)
    {
        PyEval_RestoreThread(ts);
    }
    else
    {

        PyThreadState_Swap(ts);
    }
    std::string str = "def script():\n\timport sys\n\tsys.path.append('C:\\Python\\Python37\\Lib\\site-packages')\n\tprint(sys.path)\n\timport numpy\n\tarr = numpy.array([1, 2, 3, 4, 5])\n\tprint(arr)\nscript()";
    PyRun_SimpleString(str.c_str());
    PyThreadState_Clear(ts);
    PyThreadState_DeleteCurrent();
}

int main()
{
    Py_Initialize();
    globalthread = PyThreadState_Get();
    PyEval_SaveThread();
    std::thread t(executePythonScript);
    t.join();
    PyEval_RestoreThread(globalthread);
    //PyThreadState_Swap(globalthread);
    Py_FinalizeEx();
    return 0;
}

Thank you for pointing out the post.感谢您指出帖子。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM