curl_easy_perform 导致应用程序意外终止,服务器需要很长时间才能回复

Posted

技术标签:

【中文标题】curl_easy_perform 导致应用程序意外终止,服务器需要很长时间才能回复【英文标题】:curl_easy_perform causes app to terminate unexpectedly with server that takes long to reply 【发布时间】:2017-10-28 17:38:41 【问题描述】:

我正在使用 libcurl 向服务器发送 POST 请求。一切正常,直到我注意到有时应用程序意外终止(不是超时,它甚至没有错误消息就结束了)。我已将其缩小到 curl_esy_perform。服务器回复该请求的时间很长(使用 Postman 测试,需要 20 分钟以上,但最终会回复),我的应用程序在大约 12 分钟后崩溃,没有任何错误消息。超时设置为 3600 秒。写入内存回调根本没有被调用(它不应该因为服务器不返回部分数据)这就是我使用 curl 的方式:

curl_global_init(CURL_GLOBAL_ALL);

CURL* curl;
CURLcode res;
struct MemoryStruct chunk;
int err = -1;

chunk.memory = (PCHAR)malloc(1);
chunk.size = 0;

if (!(curl = curl_easy_init())) 
   cout << "Error initializing cURL" << endl;
   return 1;


curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_PORT, port);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlWriteMemCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (PVOID)&chunk);
curl_easy_setopt(curl, CURLOPT_USERAGENT, "libcurl-agent/1.0");
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3600);

struct curl_slist* headers = NULL;
headers = curl_slist_append(headers, "Accept: application/json");
headers = curl_slist_append(headers, "Content-Type: application/json");
headers = curl_slist_append(headers, "charsets: utf-8");

curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body);
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (long)strlen(body));

// It crashes during curl_easy_perform, after it hangs for ~12 minutes
res = curl_easy_perform(curl);

.
.
.

size_t CurlWriteMemCallback(PVOID contents, size_t size, size_t nmemb, PVOID userp)

    size_t realsize = size * nmemb;
    struct MemoryStruct *mem = (struct MemoryStruct *)userp;

    mem->memory = (PCHAR)realloc(mem->memory, mem->size + realsize + 1);
    if (!mem->memory) 
        FATAL() << "Not enough memory in cURL write memory callback";
        return 0;
    

    memcpy(&(mem->memory[mem->size]), contents, realsize);
    mem->size += realsize;
    mem->memory[mem->size] = 0;

    return realsize;

【问题讨论】:

告诉我们更多关于“崩溃”的细节! 没有什么需要添加的:就好像调用了 exit() 一样。也看到这个问题(当我使用 WinHTTP 而不是 libcurl 时,该请求会发生完全相同的事情):***.com/questions/44255828/… 【参考方案1】:

是否由于 curl 手册页中描述的有关超时信号的行为而退出进程? https://curl.haxx.se/libcurl/c/CURLOPT_TIMEOUT.html

即 "这个选项可能会导致 libcurl 使用 SIGALRM 信号来超时系统调用。"

如果您的应用程序不处理该信号,那么它将退出。

有一个选项可以在超时的情况下禁用生成此信号: “在类 unix 系统中,除非设置了 CURLOPT_NOSIGNAL,否则这可能会导致使用信号。”

希望这还不算太晚,至少可以帮助其他人。

【讨论】:

对不起哥们,这种行为发生在以前工作的一个项目中。我不记得细节了。不知何故,我设法通过了它,但我不知道如何。

以上是关于curl_easy_perform 导致应用程序意外终止,服务器需要很长时间才能回复的主要内容,如果未能解决你的问题,请参考以下文章

Libcurl 挂在 curl_easy_perform 或 curl_multi_perform 从不减少第二个参数

SwiftUI Nested ForEach 导致意外排序

使用 WinAPI 的 InternetReadFile() 进行长轮询

UwAmp 重启会导致 Chrome 页面崩溃

CURL库在C++程序中的运用浅析

UIScrollView 仅在任意 App 交互后有效