1

私は、各レイヤーが、何らかのソケット接続を使用してその上または下のレイヤーと通信するスタンドアロン プロセスであるレイヤード インフラストラクチャ上の Linux 環境で作業しています。UNIX、TCP、UDP など、プロトコルは問いません。このスキームを機能させるには、最上層または最下層以外のプロセスに、サーバー ソケットとクライアント ソケットの両方が必要です。ミューテックスで保護されたキューによって供給される各接続 (つまり、送信と受信) の実行時にスレッドを作成するホームスパン ライブラリを使用しています。このライブラリのコードは、select() 呼び出しと fd セットを使用して各ソケットを監視し、接続が独自のプロセスで分離されている場合に完全に機能します。ただし、単一のプロセスで 2 つ以上のスレッド化されたソケット ハンドラーを使用しようとすると、select() 呼び出しのデッドロックと思われるものに直面します。

使用しているテスト ケース (正式な単体テストではなく単純な .cpp モジュール) は継続的に送信しますが、受信することはありません。すべきことは、いずれかの接続ハンドラが互いに送信しているメッセージをエコーすることです。ハンドラーはソケットを介して通信するのではなく、プロセスのメモリ内でメッセージを渡すことができることを知っておくことが重要です(スレッド 1 で実行される「ルーティング」アルゴリズムによって可能になります)。スレッド 1 は、いずれかのサーバーがミューテックスで保護されたキューを介して送信するメッセージを常に送信しており、これらのミューテックスでデッド ロックしていません。

これがデバッガーで見ることができるものです

(gdb) info threads
  3 Thread 0xb7525b70 (LWP 5001)  0xb7fe2424 in __kernel_vsyscall ()
  2 Thread 0xb7d26b70 (LWP 5000)  0xb7fe2424 in __kernel_vsyscall ()
* 1 Thread 0xb7d276d0 (LWP 4999)  0xb7f64370 in std::string::length() const () from /usr/lib/libstdc++.so.6

これは、2 つのスレッドがソケットを共有していないか、1 つのソケットを介して通信しようとしていないため、同じソケットでデッド ロックしているという問題ではありません。競合するselect()呼び出しによりプロセスが何度も中断されているように見えるため、どちらの接続ハンドラも送信メッセージをソケットに書き込むことができません。両方の接続のタイムアウトを 1 usec に設定しようとしましたが、効果はありませんでした。

アスキーマップ:

thread 2                                 thread 1               thread 3
[[server socket a] <-> [server a]] <-> [intermediary] <-> [[server b] <-> [server socket b]]

詳細が役立つ場合は、ライブラリからコードを投稿できます (とにかく FOSS リリースを計画しています)。これをデッドロックと断定できる人がいる場合、さらに一歩進んで回避策を推奨できますか?

ありがとう!

4

0 に答える 0