1

マルチスレッドで boost.python C/C++ プログラムを開発しています。

main()、スレッドを作成します。

PyEval_InitThreads();

pthread_create( &id, &detached_attr, newThread, NULL );

・newThread()では、2つのPy_*関数を呼び出しています。

Py_Initialize();

PyGILState_STATE gstate = PyGILState_Ensure();

hoge()次に、inという名前の C++ 関数を呼び出しますnewThread()

void hoge(){
    py::object main_module;
    py::object main_namespace;

    try {
        main_module = py::import("__main__");   //segmentation fault
        main_namespace = main_module.attr("__dict__");
    } catch (py::error_already_set const &) {
        PyErr_Print();
    }

    //Some boost python code
}

gdb バック トレース出力はこちらです。

(gdb) bt
#0  0x4032fe24 in __ctype_b_loc () from /lib/libc.so.6
#1  0x4032fde8 in __ctype_b_loc () from /lib/libc.so.6

なぜimport()失敗するのですか?何も思いつきません。この問題を解決する方法を教えてください。



-- 12/12/28 編集 ---

次の方法を使用してこの問題を解決しました。

main()、実行します

Py_Initialize();
PyEval_InitThreads();
PyEval_ReleaseLock();

次に、新しいスレッドを作成します。新しいスレッドで、私は実行します

PyGILState_STATE gstate = PyGILState_Ensure();
CALL SOME PYTHON CODE
PyGILState_Release(gstate);

しかし、なぜこれが今機能するのかわかりません。誰か理由を教えてくれませんか?

4

1 に答える 1

0

Python は、他の多くのインタープリター言語と同様に、グローバル インタープリター ロック (または GIL) を利用してスレッド セーフ (この wiki を参照) を実現し、2 つの Python インタープリター呼び出しが並行して動作するのを防ぎます。したがって、発行するすべての Python 呼び出しは、最初にロックを要求し、コマンドを実行してからロックを解放する必要があります。そのルールに従う必要があります。そうしないと、例のようにインタープリターがクラッシュする可能性があります。hoge()関数が GIL を要求しなかったため、クラッシュしたことに注意してください。

ここで、GIL リクエスト (または「保証」) とリリース関数呼び出しでコードをラップしても、すべてが解決するわけではありません。2 つのスレッドがある場合、両方が GIL にアクセスできることを確認する必要があります。メイン スレッドで GIL を解放しなかったとしたら、実際に Python を実行する 2 番目のスレッドは永久にブロックされてしまいます。あなたはそれを試しましたか?そうでない場合は、何が起こるかを確認してください。

正しい解決策 - 自分で見つけた解決策は、すべてのスレッドで GIL を取得して解放し、他のスレッドが飢えている間に GIL を持つスレッドの 1 つにスタックしないようにすることです。

于 2013-02-08T14:09:50.717 に答える