我们有一个网络应用程序,它将在各种脚本中用于与其他系统进行通信。
有时,脚本会挂起对我们网络应用程序的调用。我们最近经历了一次挂起,我试图调试这个特定应用程序的挂起过程。
此应用程序由客户端和服务器(守护程序)组成,挂起发生在客户端。
Strace输出显示它挂在选择系统调用上。
> strace -p 34567
select(4, [3], NULL, NULL, NULL
正如您所看到的,在select调用中没有给出超时,如果文件描述符“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。
答案 0 :(得分:5)
FIN_WAIT2
表示您的应用已向对等方发送了FIN
数据包,但尚未从对等方收到FIN
。在TCP中,优雅的关闭需要来自双方的FIN
。服务器守护程序未运行的事实意味着守护程序退出(或被杀死)而不通知其对等方(您)。因此,您的select()
正在等待它将不再接收的数据包,并且必须等待操作系统使用内部超时使套接字无效,这可能需要很长时间。这就是为什么你应该从不使用无限超时的情况。使用适当的超时并在超时结束时采取相应措施。