@@ -114,6 +114,12 @@ static std::size_t ReadFunction( // NOLINT(misc-use-anonymous-namespace)
114114 return writev->MoveTo (absl::MakeSpan (buffer, size * nitems));
115115}
116116
117+ // Instead of trying to send any more bytes from userdata, aborts.
118+ static std::size_t ReadFunctionAbort ( // NOLINT(misc-use-anonymous-namespace)
119+ char *, std::size_t , std::size_t , void *) {
120+ return CURL_READFUNC_ABORT;
121+ }
122+
117123static int SeekFunction ( // NOLINT(misc-use-anonymous-namespace)
118124 void * userdata, curl_off_t offset, int origin) {
119125 auto * const writev = reinterpret_cast <WriteVector*>(userdata);
@@ -482,6 +488,22 @@ std::size_t CurlImpl::HeaderCallback(absl::Span<char> response) {
482488 response.size ());
483489}
484490
491+ class CurlImpl ::ReadFunctionAbortGuard {
492+ public:
493+ explicit ReadFunctionAbortGuard (CurlImpl& impl) : impl_(impl) {}
494+ ~ReadFunctionAbortGuard () {
495+ // If curl_closed_ is true, then the handle has already been recycled and
496+ // attempting to set an option on it will error.
497+ if (!impl_.curl_closed_ ) {
498+ impl_.handle_ .SetOptionUnchecked (CURLOPT_READFUNCTION,
499+ &ReadFunctionAbort);
500+ }
501+ }
502+
503+ private:
504+ CurlImpl& impl_;
505+ };
506+
485507Status CurlImpl::MakeRequestImpl (RestContext& context) {
486508 TRACE_STATE () << " , url_=" << url_;
487509
@@ -504,6 +526,11 @@ Status CurlImpl::MakeRequestImpl(RestContext& context) {
504526 handle_.SetOptionUnchecked (CURLOPT_HTTP_VERSION,
505527 VersionToCurlCode (http_version_));
506528
529+ // All data in the WriteVector should be written after ReadImpl returns unless
530+ // an error, typically a timeout, has occurred. Use ReadFunctionAbortGuard to
531+ // leverage RAII to instruct curl to not attempt to send anymore data on this
532+ // handle regardless if an error or exception is encountered.
533+ ReadFunctionAbortGuard guard (*this );
507534 auto error = curl_multi_add_handle (multi_.get (), handle_.handle_ .get ());
508535
509536 // This indicates that we are using the API incorrectly. The application
0 commit comments