@@ -114,6 +114,12 @@ static std::size_t ReadFunction( // NOLINT(misc-use-anonymous-namespace)
114
114
return writev->MoveTo (absl::MakeSpan (buffer, size * nitems));
115
115
}
116
116
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
+
117
123
static int SeekFunction ( // NOLINT(misc-use-anonymous-namespace)
118
124
void * userdata, curl_off_t offset, int origin) {
119
125
auto * const writev = reinterpret_cast <WriteVector*>(userdata);
@@ -482,6 +488,22 @@ std::size_t CurlImpl::HeaderCallback(absl::Span<char> response) {
482
488
response.size ());
483
489
}
484
490
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
+
485
507
Status CurlImpl::MakeRequestImpl (RestContext& context) {
486
508
TRACE_STATE () << " , url_=" << url_;
487
509
@@ -504,6 +526,11 @@ Status CurlImpl::MakeRequestImpl(RestContext& context) {
504
526
handle_.SetOptionUnchecked (CURLOPT_HTTP_VERSION,
505
527
VersionToCurlCode (http_version_));
506
528
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 );
507
534
auto error = curl_multi_add_handle (multi_.get (), handle_.handle_ .get ());
508
535
509
536
// This indicates that we are using the API incorrectly. The application
0 commit comments