【问题标题】:Select system call hangs indefinitely in a n/w application.Select 系统调用在 n/w 应用程序中无限期挂起。
【发布时间】:2014-02-26 01:38:54
【问题描述】:

我们有一个网络应用程序,它将在各种脚本中用于与其他系统进行通信。

有时脚本会在调用我们的网络应用程序时挂起。我们最近遇到了挂起,我尝试调试这个特定应用程序的挂起进程。

这个应用程序由一个客户端和一个服务器(一个守护进程)组成,挂起发生在客户端。

Strace 输出显示它已挂在 select 系统调用上。

> strace -p 34567
select(4, [3], NULL, NULL, NULL

如您所见,选择调用没有超时,如果文件描述符“3”尚未准备好读取,它可以无限期阻塞。

lsof 输出显示 fd '3' 处于 FIN_WAIT2 状态。

> lsof -p 34567
client  34567 user 3u  IPv4 55184032 TCP client-box:smar-se-port2->server:daemon (FIN_WAIT2)

以上信息是否暗示了什么? FIN_WAIT2 状态?我检查了服务器端(应该运行相应的守护进程),但服务器端没有运行守护进程。我的猜测是守护进程成功运行并将输出发送到客户端,它应该可以在 fd '3' 上读取,但客户端上的 select() 调用永远不会出现,并且仍在等待发生某些事情!

我不确定为什么它永远不会出现在 select() 调用中,这只是偶尔发生,大多数时候应用程序都可以正常工作。

有什么线索吗?

服务器和客户端都是 SuSE Linux。

【问题讨论】:

    标签: linux sockets network-programming


    【解决方案1】:

    FIN_WAIT2 表示您的应用已向对等方发送了FIN 数据包,但尚未收到对等方的FIN。在 TCP 中,优雅的关闭需要来自双方的FIN。服务器守护程序未运行的事实意味着守护程序退出(或被杀死)而没有通知其对等方(您)。因此,您的select() 正在等待它将不再接收的数据包,并且必须等待操作系统使用内部超时使套接字无效,这可能需要很长时间。这就是您应该从不使用无限超时的原因。使用适当的超时时间并在超时时间过后采取相应措施。

    【讨论】:

    • 谢谢!客户端将如何收到 FIN 数据包通知? read() 调用返回零?
    • 是的。 select() 也会报告套接字是可读的。优雅地结束连接的典型方法是首先shutdown()连接结束的发送部分(发送FIN),然后继续阅读,直到没有任何内容可供阅读(如果收到FIN,或发生错误/超时),然后关闭套接字。
    • 但是我不明白的是,为什么客户端向服务器发送了一个FIN数据包?代码方面,close() 调用仅在 select() 之后,只有通过 select() 才能到达那里。但是,在客户端的分叉进程上有一个 shutdown() 调用(实际上是用于将数据发送到服务器,父客户端仅读取输出)。 shutdown() 是否也会导致应用发送 FIN 数据包?
    • 是的,shutdown() 仅用于读取,它是shutdown(sock_fd, 1);
    • shutdown(1) 表示不允许后续发送的套接字,它还会向对等方发送FIN 表示不再发送数据的信号。调用方仍然可以接收数据,直到对等方发送自己的FIN 或发生错误。
    猜你喜欢
    • 2020-09-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-31
    • 2023-03-25
    • 1970-01-01
    • 2016-01-17
    • 1970-01-01
    相关资源
    最近更新 更多