title: curl_easy_perform() crashing on Ubuntu Server 14
body: <p>Here's my upload function.</p>
  
  <p>The goal is: <strong>to upload only a chunk of a file depending on the offset and chunk size</strong></p>
  
  <p>In this function, if <code>p_offset</code> is not zero, I call <code>fseek()</code>by myself and then I let libcurl read the contents of the file using <code>fread()</code>.</p>
  
  <p>The caller of the function is responsible for giving a correct and valid size of chunk, making sure that <code>p_offset + p_sizeOfChunk &lt;= ACTUAL_SIZE_OF_FILE</code></p>
  
  <p>The answer from the server is supposed to be a string. I get it via my callback <code>writeToString()</code></p>
  
  <p><strong>The code works fine on Windows and OS X. But <code>curl_easy_perform()</code> crashes on sometimes on Ubuntu 14.</strong></p>
  
  <p>Is there anything in my code that I am missing that could cause this crash?</p>
  
  <pre><code>void uploadFile( const string &amp; p_filename, const string &amp; p_url, size_t p_offset, size_t p_sizeOfChunk )
  {
      FILE * file( fopen( p_filename.c_str(), "rb" ) );
  
      if ( !file )
      {
          throw Exception( __FILE__, __LINE__ ) &lt;&lt; "Could not open file " &lt;&lt; p_filename &lt;&lt; " when posting to " &lt;&lt; p_url;
      }
  
      if ( p_offset )
      {
          if ( fseek( file, (long)p_offset, SEEK_SET ) )
          {
              throw Exception( __FILE__, __LINE__ ) &lt;&lt; "Could not seek in file " &lt;&lt; p_filename &lt;&lt; " when posting to " &lt;&lt; p_url;
          }
      }
  
      CURL * curl( curl_easy_init() );
  
      if ( !curl )
      {
          throw Exception( __FILE__, __LINE__ ) &lt;&lt; "Could not initialize cURL when posting " &lt;&lt; p_filename &lt;&lt; " to " &lt;&lt; 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, &amp;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 &amp;&amp; res != CURLE_SEND_ERROR )
      {
          curl_easy_cleanup( curl );
          throw Exception( __FILE__, __LINE__ ) &lt;&lt; "cURL error when posting " &lt;&lt; p_filename &lt;&lt; " to " &lt;&lt; p_url &lt;&lt; ": " &lt;&lt; errorBuffer;
      }
  
      long httpResponseCode( 0 );
      curl_easy_getinfo( curl, CURLINFO_RESPONSE_CODE, &amp;httpResponseCode );
      curl_easy_cleanup( curl );
  
      if ( ( httpResponseCode / 100 ) != 2 )
      {
          cout &lt;&lt; answer &lt;&lt; endl;
          throw Exception( __FILE__, __LINE__ ) &lt;&lt; "HTTP error " &lt;&lt; httpResponseCode &lt;&lt; " when posting " &lt;&lt; p_filename;
      }
  }
  </code></pre>
  
  <p>I get the answer and record it on a <code>std::string</code> with <code>writeToString()</code>. It's for sure not the reason for the crash. I tested it just returning the <code>size * count</code> and the crash still happens.</p>
  
  <pre><code>static size_t writeToString( const void * ptr, size_t size, size_t count, FILE * stream )
  {
      string &amp; retContent( *( reinterpret_cast&lt; string * &gt;( stream ) ) );
  
      if ( !retContent.length() )
      {
          int skipBOM( ( reinterpret_cast&lt; const unsigned char * &gt;( ptr )[ 0 ] == 0xEF &amp;&amp; reinterpret_cast&lt; const unsigned char * &gt;( ptr )[ 1 ] == 0xBB &amp;&amp; reinterpret_cast&lt; const unsigned char * &gt;( ptr )[ 2 ] == 0xBF ) ? 3 : 0 );
          retContent += string( static_cast&lt; const char * &gt;( ptr ) + skipBOM, static_cast&lt; int &gt;( size * count ) - skipBOM );
      }
      else
      {
          retContent += string( static_cast&lt; const char * &gt;( ptr ), size * count );
      }
  
      return size * count;
  }
  </code></pre>
  
  <p>Here is the stack in the moment of crash! It seems to be related to OpenSSL.</p>
  
  <pre><code>#0  0x00007ffff65ad35d in write () at ../sysdeps/unix/syscall-template.S:81
  #1  0x00007ffff73187a6 in ?? () from /lib/x86_64-linux-gnu/libcrypto.so.1.0.0
  #2  0x00007ffff731684b in BIO_write () from /lib/x86_64-linux-gnu/libcrypto.so.1.0.0
  #3  0x00007ffff6ffcb72 in ?? () from /lib/x86_64-linux-gnu/libssl.so.1.0.0
  #4  0x00007ffff6ffd273 in ?? () from /lib/x86_64-linux-gnu/libssl.so.1.0.0
  #5  0x00007ffff76873e1 in ossl_send (conn=0x7ffef8013b28, sockindex=0, mem=0x7ffef8005379, len=16384, curlcode=0x7fff127fa5c0) at vtls/openssl.c:2720
  #6  0x00007ffff762fe0f in Curl_write (conn=0x7ffef8013b28, sockfd=64, mem=0x7ffef8005379, len=16384, written=0x7fff127fa608) at sendf.c:233
  #7  0x00007ffff764fb01 in readwrite_upload (data=0x7ffef8000a78, conn=0x7ffef8013b28, k=0x7ffef8000af0, didwhat=0x7fff127fa664) at transfer.c:954
  #8  0x00007ffff764fdd9 in Curl_readwrite (conn=0x7ffef8013b28, done=0x7fff127fa6dc) at transfer.c:1059
  #9  0x00007ffff765ced7 in multi_runsingle (multi=0x7ffef800a668, now=..., data=0x7ffef8000a78) at multi.c:1484
  #10 0x00007ffff765d60c in curl_multi_perform (multi_handle=0x7ffef800a668, running_handles=0x7fff127fa870) at multi.c:1759
  #11 0x00007ffff7652103 in easy_transfer (multi=0x7ffef800a668) at easy.c:705
  #12 0x00007ffff7652311 in easy_perform (data=0x7ffef8000a78, events=false) at easy.c:793
  #13 0x00007ffff7652364 in curl_easy_perform (easy=0x7ffef8000a78) at easy.c:812
  #14 ...
  </code></pre>