問題は、 fork() が呼び出しスレッドをコピーするだけであり、子スレッドに保持されているミューテックスはすべて、フォークされた子で永久にロックされることです。 pthread ソリューションは pthread_atfork()
でした ハンドラー。アイデアは、1 つのプリフォーク、1 つの親ハンドラー、および 1 つの子ハンドラーの 3 つのハンドラーを登録できるというものでした。 fork()
のとき fork の前に prefork が呼び出され、すべてのアプリケーションミューテックスを取得することが期待されます。親と子の両方が、親プロセスと子プロセスのすべてのミューテックスをそれぞれ解放する必要があります。
しかし、これで話は終わりではありません!ライブラリは pthread_atfork
を呼び出します ライブラリ固有のミューテックスのハンドラーを登録します。たとえば、Libc はこれを行います。これは良いことです。アプリケーションは、サード パーティのライブラリが保持するミューテックスを認識できない可能性があるため、各ライブラリは pthread_atfork
を呼び出す必要があります。 fork()
が発生した場合に自身のミューテックスが確実にクリーンアップされるようにする .
問題は、pthread_atfork
という順序です。 関連のないライブラリに対して呼び出されるハンドラは定義されていません (ライブラリがプログラムによってロードされる順序に依存します)。したがって、これは技術的には、競合状態のためにプリフォーク ハンドラー内でデッドロックが発生する可能性があることを意味します。
たとえば、次のシーケンスを考えてみましょう:
<オール>fork()
を呼び出します デッドロックがあり、独自のミューテックスやコードとは無関係です。
これは、私がかつて取り組んだプロジェクトで実際に起こりました。そのときに私が見つけたアドバイスは、フォークまたはスレッドを選択することでしたが、両方ではありませんでした.しかし、一部のアプリケーションではおそらく実用的ではありません。
very である限り、マルチスレッド プログラムで fork しても安全です。 fork と exec の間のコードに注意してください。そのスパンでは、再入可能 (別名、非同期セーフ) システム コールのみを作成できます。理論的には、そこで malloc したり解放したりすることは許可されていませんが、実際にはデフォルトの Linux アロケータは安全であり、Linux ライブラリはそれに依存するようになりました 最終結果は、しなければならない デフォルトのアロケーターを使用してください。