之前想做个挂stage1st论坛在线时间的工具,用C#写出来以后虽然用着也确实可以登录和浏览,但是用mono在vps的linux系统上跑,内存占了实在是有点多,想到vps本来内存就这么小,还跑了一大堆奇怪的服务,最后作罢。
但是果然想想还是不甘心,于是就又操起C++来弄,调用了CURL函数库来搞,这样windows和Linux下就都可以使用了。弄好以后也确实可以运行,于是就这么挂着。
为了详细知道这工具现在在干什么,所以我让它输出当前动作的信息。挂了几天之后,发现好像没有新的信息输出了。用gdb附加上去看调用栈,卡在curl_select里面了(和自己的代码的接口是curl_easy_perform)。这个时候的工具在输出信息的时候还不会附上当前的时间,所以也不太确定到底什么时候出的问题。于是我就改了一下代码,在输出的地方加上了时间,然后挂着。今天下午又发现它卡着了,看了时间,卡了2个多小时了。用gdb再附加上去,还是那个地方卡着。
我觉得这不像是自己的问题啊,卡在那里面了我也没办法来着。于是搜“curl_select hang”,确实也有人反映有一样的问题。但是没找到解决方法。然后就又搜索“curl_easy_perform 卡住了”,这下找到有人说关于这个的问题了。
在使用libcurl时, jwisp发现, curl_easy_perform是阻塞的方式进行下载的, curl_easy_perform执行后,程序会在这里阻塞等待下载结束(成功结束或者失败结束).此时若正常下载一段时间后,进行网络中断, curl_easy_perform并不会返回失败,而是阻塞整个程序卡在这里,此时即使网络连接重新恢复, curl_easy_perform也无法恢复继续下载,导致整个程序出现”死机”状态.
而下面的解决方法提到使用multi接口可以自己控制超时等的问题,然后我也就没继续看下去而直接使用multi接口来搞了。
它那个multi的接口大概意思是,首先弄个multi的handle,然后把easy的handle绑上去,之后perform是非阻塞的。我自己也没多试验,比如是不是一定要先perform,能不能先select之类。于是就按照curl自己给出的例子,perform一次以后,拿fd_set,然后在fd_set上调用select,然后再perform,重复到结束为止。因为select是自己调用的,所以可以比较方便设置超时时间。
虽然我在看文档的时候发现curl其实有一个opt给出设置超时时间的,但是这个设置好像只有某个特定版本之后才添加的,服务器用yum安装的curl版本实在是比较低,看着不像是有这个设置的样子,……于是没有试验。
现在代码放服务器上跑着,跑个几天看看还有没有出现卡着的问题。