curl_easy_perform()在Ubuntu Server 14上崩溃

时间:2014-05-05 22:08:48

标签: c++ ubuntu curl openssl libcurl

这是我的上传功能。

目标是:根据偏移量和块大小仅上传文件块

在此函数中,如果p_offset不为零,我自己调用fseek()然后让libcurl使用fread()读取文件的内容。

该函数的调用者负责提供正确且有效的块大小,确保p_offset + p_sizeOfChunk <= ACTUAL_SIZE_OF_FILE

服务器的答案应该是一个字符串。我是通过我的回调writeToString()

得到的

该代码在Windows和OS X上运行良好。但{J}有时在Ubuntu 14上崩溃。

我的代码中是否有任何可能导致此崩溃的错误?

curl_easy_perform()

我得到答案并将其记录在void uploadFile( const string & p_filename, const string & p_url, size_t p_offset, size_t p_sizeOfChunk ) { FILE * file( fopen( p_filename.c_str(), "rb" ) ); if ( !file ) { throw Exception( __FILE__, __LINE__ ) << "Could not open file " << p_filename << " when posting to " << p_url; } if ( p_offset ) { if ( fseek( file, (long)p_offset, SEEK_SET ) ) { throw Exception( __FILE__, __LINE__ ) << "Could not seek in file " << p_filename << " when posting to " << p_url; } } CURL * curl( curl_easy_init() ); if ( !curl ) { throw Exception( __FILE__, __LINE__ ) << "Could not initialize cURL when posting " << p_filename << " to " << p_url; } // URL curl_easy_setopt( curl, CURLOPT_URL, p_url.c_str() ); // PUT HTTP method string answer; curl_easy_setopt( curl, CURLOPT_UPLOAD, 1L ); curl_easy_setopt( curl, CURLOPT_READFUNCTION, fread ); curl_easy_setopt( curl, CURLOPT_READDATA, file ); curl_easy_setopt( curl, CURLOPT_WRITEFUNCTION, writeToString ); curl_easy_setopt( curl, CURLOPT_WRITEDATA, &answer ); curl_easy_setopt( curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)p_sizeOfChunk ); char errorBuffer[ CURL_ERROR_SIZE + 1 ]; curl_easy_setopt( curl, CURLOPT_ERRORBUFFER, errorBuffer ); // No signal handlers... curl_easy_setopt( curl, CURLOPT_NOSIGNAL, 1 ); curl_easy_setopt( curl, CURLOPT_TIMEOUT_MS, 120000 ); // HEADER char contentLength[ 512 ]; snprintf( contentLength, sizeof( contentLength ), "Content-Length: %zu", p_sizeOfChunk ); struct curl_slist * headers( nullptr ); headers = curl_slist_append( headers, contentLength ); curl_easy_setopt( curl, CURLOPT_HTTPHEADER, headers ); // SSL curl_easy_setopt( curl, CURLOPT_CAINFO, "path/to/cacert.pem" ); CURLcode res( curl_easy_perform( curl ) ); fclose( file ); if ( res != CURLE_OK && res != CURLE_SEND_ERROR ) { curl_easy_cleanup( curl ); throw Exception( __FILE__, __LINE__ ) << "cURL error when posting " << p_filename << " to " << p_url << ": " << errorBuffer; } long httpResponseCode( 0 ); curl_easy_getinfo( curl, CURLINFO_RESPONSE_CODE, &httpResponseCode ); curl_easy_cleanup( curl ); if ( ( httpResponseCode / 100 ) != 2 ) { cout << answer << endl; throw Exception( __FILE__, __LINE__ ) << "HTTP error " << httpResponseCode << " when posting " << p_filename; } } std::string上。这肯定不是崩溃的原因。我测试它只是返回writeToString()并且崩溃仍然发生。

size * count

这是崩溃时刻的堆栈!它似乎与OpenSSL有关。

static size_t writeToString( const void * ptr, size_t size, size_t count, FILE * stream )
{
    string & retContent( *( reinterpret_cast< string * >( stream ) ) );

    if ( !retContent.length() )
    {
        int skipBOM( ( reinterpret_cast< const unsigned char * >( ptr )[ 0 ] == 0xEF && reinterpret_cast< const unsigned char * >( ptr )[ 1 ] == 0xBB && reinterpret_cast< const unsigned char * >( ptr )[ 2 ] == 0xBF ) ? 3 : 0 );
        retContent += string( static_cast< const char * >( ptr ) + skipBOM, static_cast< int >( size * count ) - skipBOM );
    }
    else
    {
        retContent += string( static_cast< const char * >( ptr ), size * count );
    }

    return size * count;
}

2 个答案:

答案 0 :(得分:1)

首先......用调试器运行它(或获得适当的核心转储)以找出真正失败的地方。

不确定这可能是问题...但是查看documentation,您在CURLOPT_WRITEFUNCTION中传递的功能必须具有以下签名。

size_t function( char *ptr, size_t size, size_t nmemb, void *userdata);

但是在你的情况下:

size_t writeToString(const void * ptr, size_t size, size_t count, FILE * stream);

显然,CURLOPT_WRITEFUNCTION的默认实现需要一个FILE * ......但是在void * form

答案 1 :(得分:1)

问题在于我完全被误解了。

curl_easy_setopt( curl, CURLOPT_NOSIGNAL, 1 );

CURLOPT_NOSIGNAL 的影响阻止了 libcurl处理任何信号!我原来的解释完全相反。发生错误是因为在OS X上它正在工作[并且管道处理也存在],所以我认为&#34;信号管理&#34;是对的。我不知道为什么在OS X上同样的错误并没有显示出来。无论如何,我删除了这一行,它完美地运作。

当然,另一种可能的解决方案是将ir设置为零:

curl_easy_setopt( curl, CURLOPT_NOSIGNAL, 0 );
相关问题