GNU/Linux >> Linux の 問題 >  >> Linux

スレッド内からフォークしても安全ですか?

問題は、 fork() が呼び出しスレッドをコピーするだけであり、子スレッドに保持されているミューテックスはすべて、フォークされた子で永久にロックされることです。 pthread ソリューションは pthread_atfork() でした ハンドラー。アイデアは、1 つのプリフォーク、1 つの親ハンドラー、および 1 つの子ハンドラーの 3 つのハンドラーを登録できるというものでした。 fork()のとき fork の前に prefork が呼び出され、すべてのアプリケーションミューテックスを取得することが期待されます。親と子の両方が、親プロセスと子プロセスのすべてのミューテックスをそれぞれ解放する必要があります。

しかし、これで話は終わりではありません!ライブラリは pthread_atfork を呼び出します ライブラリ固有のミューテックスのハンドラーを登録します。たとえば、Libc はこれを行います。これは良いことです。アプリケーションは、サード パーティのライブラリが保持するミューテックスを認識できない可能性があるため、各ライブラリは pthread_atfork を呼び出す必要があります。 fork() が発生した場合に自身のミューテックスが確実にクリーンアップされるようにする .

問題は、pthread_atfork という順序です。 関連のないライブラリに対して呼び出されるハンドラは定義されていません (ライブラリがプログラムによってロードされる順序に依存します)。したがって、これは技術的には、競合状態のためにプリフォーク ハンドラー内でデッドロックが発生する可能性があることを意味します。

たとえば、次のシーケンスを考えてみましょう:

<オール>
  • スレッド T1 が fork() を呼び出します
  • libc prefork ハンドラは T1 で呼び出されます (たとえば、T1 はすべての libc ロックを保持します)
  • 次に、スレッド T2 で、サードパーティ ライブラリ A が独自のミューテックス AM を取得し、ミューテックスを必要とする libc 呼び出しを行います。 libc ミューテックスは T1 によって保持されているため、これはブロックされます。
  • スレッド T1 はライブラリ A の prefork ハンドラを実行します。ライブラリ A は、T2 によって保持されている AM の取得を待機してブロックします。
  • デッドロックがあり、独自のミューテックスやコードとは無関係です。

    これは、私がかつて取り組んだプロジェクトで実際に起こりました。そのときに私が見つけたアドバイスは、フォークまたはスレッドを選択することでしたが、両方ではありませんでした.しかし、一部のアプリケーションではおそらく実用的ではありません。


    very である限り、マルチスレッド プログラムで fork しても安全です。 fork と exec の間のコードに注意してください。そのスパンでは、再入可能 (別名、非同期セーフ) システム コールのみを作成できます。理論的には、そこで malloc したり解放したりすることは許可されていませんが、実際にはデフォルトの Linux アロケータは安全であり、Linux ライブラリはそれに依存するようになりました 最終結果は、しなければならない デフォルトのアロケーターを使用してください。


    Linux
    1. Bashスクリプト内からフルパスを取得しますか?

    2. C プログラム内からプログラムを実行する

    3. ファイル内から単一のバイト チャンクを抽出するにはどうすればよいですか?

    1. スレッド ID とスレッド ハンドル

    2. コンテナー自体から Docker Linux コンテナー情報を取得するにはどうすればよいですか?

    3. 影響を受ける VM 内からメモリ バルーニングを検出する

    1. シェルスクリプト内から passwd コマンドを使用する

    2. 別のスレッドからスレッドローカルにアクセスする

    3. tmux 内からデフォルトの新しいウィンドウ ディレクトリを変更する方法