如何中断执行阻塞套接字连接的线程?

时间:2012-06-09 15:24:57

标签: multithreading sockets interrupt system-calls

我有一些代码产生pthread,试图维持与远程主机的套接字连接。如果连接丢失,它会尝试使用其套接字上的阻塞connect()重新连接。由于代码在一个单独的线程中运行,我并不关心它使用同步套接字API的事实。

也就是说,直到我的应用程序退出时。我想执行一些有序关闭的外观,所以我使用线程同步原语唤醒线程并发出信号让它退出,然后在线程上执行pthread_join()等待它完成。这很有效,除非在我命令关闭时线程处于connect()调用的中间。在这种情况下,我必须等待连接超时,这可能需要很长时间。这使得应用程序似乎需要很长时间才能关闭。

我想做的是以某种方式中断对connect()的调用。调用返回后,线程会注意到我的退出信号并干净地关闭。由于connect()是系统调用,我认为我可以使用信号故意中断它(从而使调用返回EINTR),但我不确定这是否是一个强大的方法在POSIX线程环境中。

是否有人建议如何使用信号或通过其他方法?请注意,connect()调用在某些库代码中无法修改,因此无法修改,因此无法选择更改为非阻塞套接字。

1 个答案:

答案 0 :(得分:6)

尝试关闭()套接字以中断 connect()。我不确定,但我认为它至少可以在Linux上运行。当然,要小心正确同步,这样你只能关闭()这个套接字一次,或者第二个 close()理论上可以关闭一个不相关的文件描述符打开。

编辑 shutdown ()可能更合适,因为它实际上并未关闭套接字。

或者,您可能需要查看pthread_cancel()pthread_kill()。但是,我没有办法在没有竞争条件的情况下使用这两种方法。

我建议您放弃多线程服务器方法,而是使用事件驱动,例如使用epoll进行事件通知。通过这种方式,您可以避免所有这些基本问题变得非常困难,例如正确关闭。您可以随时做任何您想做的事情,例如:安全关闭插座,再也听不到它们了。

另一方面,如果在您的工作线程中,您执行非阻塞 connect()并通过epoll_pwait()(或 ppoll()或<获得通知em> pselect();注意 p ),您可以避免与信号相关的竞争条件。