Ich bin den Python-Interpreter in eine Multithread-C-Anwendung einbetten und ich bin ein wenig verwirrt, welche APIs ich verwenden sollte, um Thread-Sicherheit zu gewährleisten.Einbetten von Python in Multithread-C-Anwendung
Nach dem, was ich gesammelt habe, ist es beim Einbetten von Python Sache des Embedders, sich um die GIL-Sperre zu kümmern, bevor irgendein anderer Python C-API-Aufruf aufgerufen wird. Dies wird mit diesen Funktionen getan:
gstate = PyGILState_Ensure();
// do some python api calls, run python scripts
PyGILState_Release(gstate);
Doch dies allein scheint nicht genug zu sein. Ich habe immer noch zufällige Abstürze, da es nicht mutual exclusion für den Python-APIs zur Verfügung zu stellen scheint.
Nach etwas mehr docs lese ich auch hinzugefügt:
PyEval_InitThreads();
direkt nach dem Aufruf Py_IsInitialized()
aber das ist, wo der verwirrende Teil kommt. Die docs sagen, dass diese Funktion:
initialisieren und erwerben die globale Interpreter
sperren Dies deutet darauf hin, dass, wenn diese Funktion zurückkehrt, wird die GIL soll gesperrt werden und sollte irgendwie freigeschaltet werden. aber in der Praxis scheint dies nicht erforderlich zu sein. Mit dieser Linie an Ort und Stelle war mein multithreaded perfekt und gegenseitiger Ausschluß wurde von den PyGILState_Ensure/Release
Funktionen beibehalten.
Als ich versuchte, PyEval_ReleaseLock()
nach PyEval_ReleaseLock()
hinzuzufügen, wurde die App ziemlich schnell in einem nachfolgenden Anruf zu PyImport_ExecCodeModule()
dead-locked.
Was fehle ich hier?
Dies ist falsch und möglicherweise schädlich: 'PyEval_SaveThread' sollte immer in Verbindung mit' PyEval_RestoreThread' stehen. Wie [an anderer Stelle erläutert] (http://stackoverflow.com/a/15471525/1600898) sollten Sie nicht versuchen, die Sperre nach der Initialisierung zu lösen; Überlassen Sie es Python, um es als Teil seiner regulären Arbeit zu veröffentlichen. – user4815162342
Ich sehe nicht, warum es schädlich ist, wenn Sie alle Aufrufe an Python in einem _Block _ _Allow_ Blöcke setzen. Wenn Sie andererseits 'PyEval_SaveThread();' nicht aufrufen, blockiert Ihr Haupt-Thread den Zugriff anderer Threads auf Python. Mit anderen Worten: "PyGILState_Ensure()" Deadlocks. – khkarens
Dies ist die einzige Sache, die sowohl für das Einbetten von Python als auch das Aufrufen eines Erweiterungsmoduls funktioniert. –