AssertionError (solo 3.X) al llamar a Py_Finalize con subprocesos

Recibo una salida de error cuando llamo a Py_Finalize () de C-API desde un subproceso C diferente del que hice una llamada a python.

El error que estoy viendo es:

Exception ignored in:  Traceback (most recent call last): File "C:\Python34-32\Lib\threading.py", line 1289, in _shutdown assert tlock.locked() AssertionError: 

Esto solo sucede en Python 3.X (probado con 3.4.2), en Python 2.7 exactamente el mismo código no tiene ningún problema.

Aquí hay un ejemplo mínimo que muestra que sucede cuando se usa un hilo C, pero no cuando todo sucede en un solo hilo C:

 #include  #include  #include  #include  #include  void make_file() { std::fstream file("my_test.py", std::ios::out); file << "import threading\n" << "def my_function():\n" << " pass\n" ; file.close(); } void exec() { PyGILState_STATE gstate = PyGILState_Ensure(); PyObject* pdict = PyDict_New(); PyDict_SetItemString(pdict, "__builtins__", PyEval_GetBuiltins()); PyRun_String("import my_test", Py_file_input, pdict, pdict); PyRun_String("my_test.my_function()", Py_file_input, pdict, pdict); assert(!PyErr_Occurred()); PyGILState_Release(gstate); } void basic() { std::cout << "--Starting Basic--" << std::endl; Py_Initialize(); PyEval_InitThreads(); PyThreadState* threadState = PyEval_SaveThread(); exec(); PyEval_RestoreThread(threadState); Py_Finalize(); std::cout << "--Basic Complete--" << std::endl; } void with_thread() { std::cout << "--Starting With Thread--" << std::endl; Py_Initialize(); PyEval_InitThreads(); PyThreadState* threadState = PyEval_SaveThread(); std::thread t(exec); t.join(); PyEval_RestoreThread(threadState); Py_Finalize(); std::cout << "--With Thread Complete--" << std::endl; } int main(int argc, char* argv[]) { make_file(); basic(); with_thread(); return 0; } 

salida

 --Starting Basic-- --Basic Complete-- --Starting With Thread-- Exception ignored in:  Traceback (most recent call last): File "C:\Python34-32\Lib\threading.py", line 1289, in _shutdown assert tlock.locked() AssertionError: --With Thread Complete-- 

El orden de las llamadas básicas () / with_thread () en main no importa, incluso puedo incluir esas líneas varias veces sin ningún efecto, y cada llamada with_thread () da como resultado la salida de error.

Editar:

Haciendo el threadState global, luego cambiando exec a:

 void exec() { //PyGILState_STATE gstate = PyGILState_Ensure(); PyEval_RestoreThread(threadState); PyObject* pdict = PyDict_New(); PyDict_SetItemString(pdict, "__builtins__", PyEval_GetBuiltins()); PyRun_String("import my_test", Py_file_input, pdict, pdict); PyRun_String("my_test.my_function()", Py_file_input, pdict, pdict); assert(!PyErr_Occurred()); //PyGILState_Release(gstate); threadState = PyEval_SaveThread(); } 

hace que el error desaparezca; sin embargo, tengo un valor global que necesito para coordinar entre los usuarios de mi biblioteca (en mi código real, la función exec () podría ser escrita por cualquier persona y tengo muchas más cosas de inicialización que correr). ¿Alguna información sobre cómo hacer que GIL se aísle más, como el ejemplo original, manteniendo la compatibilidad de subprocesos?

Intenta añadiendo

 Py_DECREF(PyImport_ImportModule("threading")); 

después

 PyEval_InitThreads();