Skip to content

Commit

Permalink
FIX: crash with std::logic_error when reusing a connection that timed…
Browse files Browse the repository at this point in the history
… out on the server (#1019)

* FIX: check whether instream() is valid before trying to rewind

* add .can_seek() as a second line of defense

* apply clang-format

* improve error reporting for unrewindable streams

* Add René Meusel (reneme) to CONTRIBUTORS.txt.
  • Loading branch information
reneme authored and BillyONeal committed Jan 16, 2019
1 parent 21a609b commit be5d43f
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 1 deletion.
1 change: 1 addition & 0 deletions CONTRIBUTORS.txt
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,4 @@ Christian Deneke (chris0x44)
leetal

Benjamin Lee (mobileben)
René Meusel (reneme)
34 changes: 33 additions & 1 deletion Release/src/http/client/http_client_asio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1322,7 +1322,39 @@ class asio_context final : public request_context, public std::enable_shared_fro
// cancellation registration to maintain the old state.
// This also obtains a new connection from pool.
auto new_ctx = create_request_context(m_http_client, m_request);
new_ctx->m_request._get_impl()->instream().seek(0);

// If the request contains a valid instream, we try to rewind it to
// replay the just-failed request. Otherwise we assume that no data
// was sent in the first place.
const auto& instream = new_ctx->m_request._get_impl()->instream();
if (instream)
{
// As stated in the commit message of f4f2348, we might encounter
// streams that are not capable of rewinding and hence resending the
// request is not possible. We cannot recover from this condition and
// need to escalate it to the using code.
if (!instream.can_seek())
{
report_error("cannot rewind input stream for connection re-establishment",
ec,
httpclient_errorcode_context::readheader);
return;
}

try
{
// Rewinding the stream might throw, in which case we cannot do the
// connection re-establishment transparently. I.e. report the exception
// to the calling code.
instream.seek(0);
}
catch (...)
{
report_exception(std::current_exception());
return;
}
}

new_ctx->m_request_completion = m_request_completion;
new_ctx->m_cancellationRegistration = m_cancellationRegistration;

Expand Down

0 comments on commit be5d43f

Please sign in to comment.