![当父进程被终止时,关闭一个一直等待子进程的套接字](https://linux22.com/image/1508935/%E5%BD%93%E7%88%B6%E8%BF%9B%E7%A8%8B%E8%A2%AB%E7%BB%88%E6%AD%A2%E6%97%B6%EF%BC%8C%E5%85%B3%E9%97%AD%E4%B8%80%E4%B8%AA%E4%B8%80%E7%9B%B4%E7%AD%89%E5%BE%85%E5%AD%90%E8%BF%9B%E7%A8%8B%E7%9A%84%E5%A5%97%E6%8E%A5%E5%AD%97.png)
情况如下:
服务/父进程连接到“公共端口”(父进程是服务)。该“公共端口”为 11000。当新请求从端口 11000 到达父进程时,服务器会使用“私有”端口(套接字)将该请求发送到子进程。您知道,这是实现服务器的典型方式。
父进程被杀死但是套接字没有关闭(我还不知道原因)。
孤立进程正在等待套接字关闭,并且 pkill 不起作用(它处于不间断睡眠状态)。
我无法再次运行服务器,因为服务器说地址(0.0.0.0:11000)已被使用。
因此,我有两个选择,关闭“内部套接字”以完成孤立进程,或者以某种方式“释放”地址/端口 0.0.0.0:11000 以再次运行服务器,并使孤立进程处于等待状态。这样做是为了避免每次服务器失败时都重新启动服务器,同时我调查问题。
有关该情况的有用信息(子进程的 pid 是 1993):
$ sudo lsof -np 1993
[...]
proc 1993 root 16u IPv4 14997 0t0 TCP 127.0.0.1:42982->127.0.0.1:37528 (CLOSE_WAIT)
因此,我想要关闭的端口是 37528。相应套接字的文件描述符是 16u(或者我是这么认为的)。
$ sudo strace -p 1993
Process 1993 attached
futex(0x2fff414, FUTEX_WAIT_PRIVATE, 1, NULL
$ netstat -np
[...]
tcp 0 0 127.0.0.1:42982 127.0.0.1:37528 CLOSE_WAIT -
如果我尝试通过以下方式连接到孤立进程gdb
:
$ gdb -p 1993
Attaching to process 1993
{process_path} (deleted): No such file or directory.
我认为这是因为它的父进程被杀死了。问题是,我无法连接到孤儿进程来调用close(16u)
。
我怎样才能“解决”这种情况?
笔记:我已经尝试重新启动networking
服务,但不起作用。这是 Ubuntu Server 14.04(VirtualBox),我使用 ssh 连接到我的机器。没有网络管理器。
我已尝试将应用ifdown
到ifup
每个接口(eth0、eth1、lo 和 virbr),但它们不会关闭套接字。
答案1
没有简单的方法。首先,这与联网:关闭等待你的子进程在回复鳍数据包确认, 和前关闭套接字并向其对等端发送鳍数据包。在关闭等待说明该过程正在完成某项操作,最后它将调用关闭(),促使内核发出FIN数据包。
换句话说,在关闭等待表明该进程正在尝试完成某项操作,不是等待对方的回复;因此关闭网络、重新启动接口等都无济于事。
总的来说,这不应该本身一个大问题:有些进程挂起并没有什么错关闭等待状态。让您感到困扰的是难以理解:您声明父进程侦听端口 11000,然后在端口 37528 上联系子进程,但您声明,在父进程死亡后,您无法启动服务器的新实例,因为端口 11000 未释放。但您刚才声明不是子进程在使用它!那么是谁在使用它?
无论如何,您可以尝试一些事情;
您是否尝试过使用-9选项?这是你能想出的最强的办法。
您可以使用斯特拉斯从一开始就跟踪子进程中的系统调用(或者是子进程?),通过
strace -f YourParentProcess
这也将遵循*fork()*ed 进程。
我猜你很可能忘记这个孩子,并试图确定为什么端口 11000 似乎被占用,以及被谁占用。你应该尝试更方便的命令
ss -lntp | grep 11000
调查此事。