什么是通过接受关闭另一个线程中使用的套接字的风险?

时间:2015-01-30 16:04:48

标签: c++ c linux multithreading sockets

我有一个服务器应用程序。

服务器正在通过以下方式来自客户端的连接:

 while( (client_sock = accept(socket_desc, (struct sockaddr *)&client, (socklen_t*)&c)) )
{
     .....
 }

我有另一个在我的应用程序退出中执行的线程。在这个线程中,我关闭了套接字socket_desc

close(socket_desc);

在一个线程中关闭套接字的风险是什么,还有另一个线程在同一个套接字上接受?

3 个答案:

答案 0 :(得分:1)

据我所知,您描述的动作组合的语义没有定义,这应该足以让您找到替代方案。我推测合理可能被观察到的行为包括

  • close()快速返回,并且
    • accept()来电快速失败,可能表示EBADFEINVALENOTSOCK错误,或
    • accept()调用继续阻止,直到连接请求到达,或
    • accept()无限期阻断;或
  • close()阻止,直到accept()返回,如果有的话;或
  • close()accept()死锁。

但是,如果确实没有定义语义,那么几乎任何事情都可能发生。

如果一个不同的线程必须关闭套接字而不是它上面的一个accept()连接,那么你最好设置某种标志来指示程序正在退出,然后signal() accept()线程将其从accept()中删除。接收到这种信号的线程将从程序退出标志中知道停止而不是再次尝试accept()

如果你的线程可以取消,那么全局标志可以采用线程取消消息的形式。 accept()函数是取消点,因此您的线程将在下次调用accept()时收到取消消息。

答案 1 :(得分:1)

我可能是错的。但是,它可能适用于这样的场景: - 考虑3个线程 - A,B,C。

  1. 线程A等待套接字并进入休眠状态
  2. 线程B关闭套接字
  3. 线程C创建一个新套接字,它恰好获得与最近关闭的套接字相同的文件描述符编号(Socket也是一个文件)
  4. 线程A醒来(accept上有错误代码)然后调用 close认为意外错误=>这会影响在C !!中创建的完全不同的有效套接字

答案 2 :(得分:0)

您可以关闭套接字以中止accept函数。但是您必须更改代码,并仔细检查API函数的返回值。 while循环时你的尝试不起作用,因为它没有检查SOCK_ERROR(-1)。