当从另一个线程发出信号时,如何从阻塞套接字上的"accept"中"脱离"?

spr*_*aff 5 sockets linux multithreading

和这个人的情况相同,但我不太明白答案.

问题:

  • 线程1调用accept阻塞的套接字.
  • 线程2调用close此套接字.
  • 线程1继续阻塞.我希望它从接受回来.

解决方案:

你应该做的是向被阻止接受的线程发送信号.这将使它EINTR并且它可以干净地脱离 - 然后关闭插座.请勿从使用它的线程以外的线程中关闭它.

我不知道该做什么 - 当在线程1中接收到信号时,accept已经阻塞,并且在信号处理程序完成后将继续阻塞.

  1. 答案到底意味着什么呢?
  2. 如果线程1信号处理程序可以做一些会导致accept立即返回的事情,为什么线程2不能在没有信号的情况下做同样的事情?
  3. 有没有信号的另一种方法吗?我不想增加图书馆的警告.

mar*_*k4o 5

取而代之的阻断accept(),阻断select(),poll()或类似的电话,让您等待的活动在多个文件描述符,并使用"自管绝招"之一.传递给的所有文件描述符都select()应该处于非阻塞模式.其中一个文件描述符应该是您使用的服务器套接字accept(); 如果那个变得可读,那么你应该继续打电话accept(),它不会阻止.除了那个之外,创建一个pipe(),将其设置为非阻塞,并检查读取端是否可读.而不是close()在另一个线程中调用服务器套接字,而是将一个字节的数据发送到管道写端的第一个线程.实际的字节值无关紧要; 目的只是唤醒第一个线程.当select()指示管道可读时,read()忽略来自管道,close()服务器套接字的数据,并停止等待新连接.


Ama*_*9MF 2

如果在接受连接之前捕获到信号,accept() 调用将返回错误代码 EINTR。因此,请检查返回值和错误代码,然后相应地关闭套接字。

如果您希望完全避免信号机制,请在调用accept()之前使用select()来确定是否有任何传入连接准备好接受。select() 调用可以设置超时,以便您可以恢复并响应中止条件。

我通常在检查退出/中止条件的 while 循环中调用超时为 1000 到 3000 毫秒的 select() 。如果 select() 返回一个准备好的描述符,我调用accept(),否则我要么循环并在 select() 上再次阻塞,要么根据请求退出。