发送请求代码是
size_t WriteBack( void *ptr, size_t size, size_t nmemb, void *stream ) {
size_t realsize = size * nmemb;
string *buffer = (string*)stream;
buffer->append((const char *)ptr, realsize);
return realsize;
}
bool ProfileOperator::CurlPost(const string &url, const string &postdata, string &res_buffer)
{
CURL *curl;
CURLcode code;
curl = curl_easy_init();
if (curl){
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl, CURLOPT_POST, 1L);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postdata.c_str());
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteBack);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void*)&res_buffer);
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
LOG(DEBUG) << curl_version();
LOG(DEBUG) << "ready to send req, url: " << url << " postdata: " << postdata;
code = curl_easy_perform(curl);
curl_easy_cleanup(curl);
if( code != CURLE_OK){
LOG(WARNING) << "post req failed, res_buffer:" << res_buffer << " err:" << curl_easy_strerror(code);
return false;
}
} else {
return false;
}
return true;
}
然后在执行到 curl_easy_cleanup(curl)
函数的时候会栈溢出,gdb 信息如下
Program terminated with signal 11, Segmentation fault.
#0 0x000000330f523e44 in X509_certificate_type () from /usr/lib64/libcrypto.so.10
Missing separate debuginfos, use: debuginfo-install addops-zookeeper-client-3.4.5-1.el6.x86_64 boost153-system-1.53.0-8.el6.x86_64 boost153-thread-1.53.0-8.el6.x86_64 glibc-2.12-1.132.el6_5.2.x86_64 keyutils-libs-1.4-5.el6.x86_64 krb5-libs-1.10.3-65.el6.x86_64 libcom_err-1.41.12-24.el6.x86_64 libqlog-2.1.14-1.el6.x86
_64 libselinux-2.0.94-7.el6.x86_64 nspr-4.8.8-3.el6.x86_64 nss-3.12.10-16.el6.x86_64 nss-softokn-freebl-3.14.3-10.el6_5.x86_64 nss-util-3.12.10-2.el6.x86_64 openldap-2.4.23-20.el6.x86_64 openssl-1.0.1e-57.el6.x86_64 snappy-1.0.5-1.el6.x86_64 zlib-1.2.3-29.el6.x86_64
(gdb) bt
#0 0x000000330f523e44 in X509_certificate_type () from /usr/lib64/libcrypto.so.10
#1 0x0000003310822c3b in ssl3_check_cert_and_algorithm () from /usr/lib64/libssl.so.10
#2 0x0000003310827951 in ssl3_connect () from /usr/lib64/libssl.so.10
#3 0x0000003310830e07 in ssl23_connect () from /usr/lib64/libssl.so.10
如果我注释掉的两行 SSL 相关配置,程序就不会栈溢出,但是发送请求的时候会报错Problem with the SSL CA cert (path? access rights?)
size_t WriteBack( void *ptr, size_t size, size_t nmemb, void *stream ) {
size_t realsize = size * nmemb;
string *buffer = (string*)stream;
buffer->append((const char *)ptr, realsize);
return realsize;
}
bool ProfileOperator::CurlPost(const string &url, const string &postdata, string &res_buffer)
{
CURL *curl;
CURLcode code;
curl = curl_easy_init();
if (curl){
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl, CURLOPT_POST, 1L);
//curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
//curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postdata.c_str());
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteBack);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void*)&res_buffer);
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
LOG(DEBUG) << curl_version();
LOG(DEBUG) << "ready to send req, url: " << url << " postdata: " << postdata;
code = curl_easy_perform(curl);
curl_easy_cleanup(curl);
if( code != CURLE_OK){
LOG(WARNING) << "post req failed, res_buffer:" << res_buffer << " err:" << curl_easy_strerror(code);
return false;
}
} else {
return false;
}
return true;
}
我在 shell 里面直接执行的 curl 命令给 https 网站发送请求没问题,所以本机上的证书应该也是没有问题的,默认用的是
/etc/pki/tls/certs/ca-bundle.cr
shell 里面的 curl 版本是
curl 7.37.0 (x86_64-unknown-linux-gnu) libcurl/7.25.0 OpenSSL/1.0.0 zlib/1.2.3 c-ares/1.7.0 libidn/1.18 libssh2/1.4.2
Protocols: file ftp ftps http https ldap ldaps scp sftp telnet tftp
Features: AsynchDNS IDN Largefile NTLM NTLM_WB SSL libz TLS-SRP Metalink
libcurl 版本是
libcurl/7.65.1 OpenSSL/1.0.1e-fips zlib/1.2.3
版本虽然不一致但是 libcurl 版本和 openssl 版本都要高一点,应该兼容性更好,求问是哪里还需要配置一下吗?
1
Hallelu 2019-10-10 16:31:07 +08:00 1
libcurl 崩溃的问题之前遇到过,也是搞的头疼
libcurl 本身是线程安全的,但 openssl 不是。 设置一下禁止 libcurl 访问超市抛出的超时信号 curl_setopt(curl, CURLOPT_NOSIGNAL,1L); 还有 init 的时候,最好在主线程调用全局初始化 curl_global_init(CURL_GLOBAL_ALL); 在为 openssl 创建两个回调函数,楼主可以试试。 |