3

epoll_waitを使用して複数のスレッドを使用する複数の接続を管理すると、閉じたソケットに関連付けられたカスタムデータを解放しようとするリスクがあります。

次のシナリオを考えてみましょう。ここで、Tはカスタムデータです。

  1. データを受信し、
  2. 1のため、スレッドAはepoll_waitからブロックを解除し、イベントを処理します(アクセスT)
  3. 同時に、別のスレッドBが接続を閉じようとしています

スレッドBは、Tを安全に削除できるとは想定できませんが、closeを呼び出すと、すぐにソケットがepollから削除されます。

私は次の標準的な考えを持っていました:

書き込み/読み取りの呼び出しがEAGAINを返すたびにインクリメントされ、ソケットの準備ができるたびにデクリメントされるT内の変数を維持します。closeが呼び出されたら、その変数がゼロになるのを待ってからTを削除します。私が経験した問題は、closeが呼び出された場合、epoll_waitがソケットを準備するための以前の呼び出しのキャンセルの表示を返さないことです。

誰かがこれと同じ問題を抱えていましたか?どのようにしてそれを克服することができましたか?

4

2 に答える 2

4

ここで少なくとも3つの可能な方法:

  • シンプルでクリーンなスレッドを使用しないでください。通常は機能します。

  • 専用スレッドにすべてのファイル記述子のポーリングを実行させ、実際のI/Oと処理を実行するワーカースレッドのプールにイベントを公開させます。

  • スレッドごとに1つのepoll(7)インスタンスがあるため、スレッドは、交差しない記述子のセットを管理します。ただし、これらのセットを設定するためのリスニングソケットと、リグ全体をシャットダウンできるようにするためのeventfd(2)、または自己のような制御メカニズムは例外です。pipe(2)きれいに。

お役に立てれば。

于 2012-12-10T21:08:52.663 に答える
1

多くの調査の結果、この最近の注目すべき記事を見つけました。http: //lwn.net/Articles/520012/ 基本的に、私が説明している問題を認識し、epollAPIを拡張できるLinuxカーネルへの将来のパッチについて説明しています。問題を解決する方法。

拡張機能は、EPOLL_CTL_DISABLEという新しいコマンドをもたらします。それが発行されると、戻り値によって、呼び出し元のスレッドは、同じソケットで他のスレッドがepoll_waitからブロック解除されたかどうかを認識します。これは、カスタムデータのクローズとリリースの安全な瞬間を知るのに役立ちます。

于 2012-12-12T22:06:00.737 に答える