私はマルチスレッドCアプリケーションにPythonインタープリターを埋め込んでいますが、スレッドセーフを確保するためにどのAPIを使用すべきかについて少し混乱しています。
私が収集したものから、Pythonを埋め込む場合、他のPython C API呼び出しを呼び出す前に、GILロックを処理するのは埋め込み者次第です。これは、次の関数で実行されます。
gstate = PyGILState_Ensure();
// do some python api calls, run python scripts
PyGILState_Release(gstate);
しかし、これだけでは十分ではないようです。Python APIの相互排除を提供していないように見えるため、ランダムにクラッシュすることがあります。
さらにいくつかのドキュメントを読んだ後、私も追加しました:
PyEval_InitThreads();
呼び出しの直後Py_IsInitialized()
ですが、それが混乱を招く部分です。ドキュメントには、この関数は次のように記載されています。
グローバルインタプリタロックを初期化して取得する
これは、この関数が戻ったときに、GILがロックされているはずであり、何らかの方法でロックを解除する必要があることを示しています。しかし実際には、これは必須ではないようです。この行を配置すると、マルチスレッドが完全に機能し、PyGILState_Ensure/Release
関数によって相互排除が維持されました。に続く呼び出しでアプリがデッドロックした後、すぐに
追加しようとしたとき。PyEval_ReleaseLock()
PyEval_ReleaseLock()
PyImport_ExecCodeModule()
だから私はここで何が欠けていますか?