Hello World

记一次文件下载失败问题定位过程

2017-07-06
coderhuo

通过mongoose下载文件的时候,概率出现下载文件不完整的情况。

软件交互流程如下:

浏览器 <----HTTP连接----> web服务器mongoose <----本地TCP连接---->cgi进程


抓包发现,问题出现的时候,cgi进程发送给mongoose的文件就是不完整的。但是通过strace命令看,cgi进程是读完了整个文件并且都通过系统接口send成功了,然后正常关闭套接字的。也就是说,cgi把文件读完了,并且都通过send函数发给协议栈了,但是有部分内容协议栈并未发出去。

仔细分析报文,cgi进程和mongoose之间连接断开方式不对劲,由于是cgi主动关闭,应该是cgi端发送FIN,但是实际上cgi发出的是RST。于是找驱动组同事分析,还好该同事是个大牛,通过走读协议栈代码,发现在以下情况下close套接字会发RST而不是FIN:接收缓冲区中有数据未被应用程序读取的时候,如果应用程序close套接字,协议栈会发送RST而不是FIN,并丢弃发送缓冲中尚未发送的数据。


结合报文和代码一看,果然mongoose在连接刚建立的时候发给cgi进程一串字符串,但是cgi进程由于用不到,就一直没有去读取。如果cgi进程close连接的时候发送缓冲区已经没有数据了,那么浏览器最终下载下来的文件是完整的;如果close的时候发送缓冲区还有数据,由于数据被丢失,所以下载下来的文件是不完整的。这也是问题为什么概率出现的原因。


Comments

Content