我在分布式基础架构的Linux环境中工作,其中每个层都是独立的进程,使用某种套接字连接与其上方或下方的层进行通信。它可能是UNIX,TCP,UDP,协议无关紧要。要使此方案有效,任何不是最顶层或最底层的进程都必须同时具有服务器和客户端套接字。我们正在使用一个homespun库,它为每个连接(即发送和接收)的运行时间创建一个线程,该线程由互斥锁保护队列提供。此库中的代码使用select()调用和fd集来监视每个套接字,并且当连接在其自己的进程中被隔离时,它们可以正常工作。但是,当我们尝试在一个进程中使用两个或多个线程套接字处理程序时,我们面临的是我认为在select()调用上遇到的死锁,但我不确定。
我们正在使用的测试用例(只是一个简单的.cpp模块,而不是正式的单元测试)将不断发送但从未收到。它应该做的是回应连接处理程序相互发送的消息。重要的是要知道处理程序 NOT 通过套接字进行通信,但能够在进程的内存中传递消息(通过在线程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
这不是两个线程在同一个套接字上死锁的问题,因为它们没有共享套接字或尝试通过一个套接字进行通信。在我看来,竞争select()
调用导致进程一次又一次地挂起,因此连接处理程序都不能将传出消息写入套接字。我已经尝试将两个连接的时间设置为1 usec无效。
ascii map:
thread 2 thread 1 thread 3
[[server socket a] <-> [server a]] <-> [intermediary] <-> [[server b] <-> [server socket b]]
如果更多细节有用,我可以从我们的库中发布代码(我们计划在FOSS上发布)。如果任何人可以肯定地将其识别为死锁,那么他们是否可以再采取进一步措施并推荐解决方案?
谢谢!