chore: Revert graceful peer disconnection and follow-up fix - #7296
Conversation
Reverts the following commits: - 17a2606 "Bugfix: Adds graceful peer disconnection (#5669)" - e80642f "fix: Fix regression in ConnectAttempt (#5900)" Performed as a manual revert against current HEAD so that identifier renames landed by subsequent refactors (snake_case to camelCase methods, fee* to kFee* constants, scoped enums, etc.) are preserved.
e120d59 to
2f0efa4
Compare
There was a problem hiding this comment.
Pull request overview
This PR manually reverts prior changes that introduced a more “graceful” peer disconnect path (SSL async_shutdown + shutdown state machine) and a follow-up ConnectAttempt regression fix, while keeping later refactor renames intact.
Changes:
- Reverts PeerImp shutdown/state-machine logic back toward a simpler close path, reintroducing a
gracefulClose_-based EOF handling flow. - Reverts ConnectAttempt’s multi-step timeout/shutdown tracking to a simplified single-timer model and simpler close behavior.
- Replaces
std::set::count(...) > 0checks with C++20contains(...)inDoor.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| src/xrpld/overlay/detail/PeerImp.h | Removes extensive shutdown documentation/state, adds new flags and reshapes close/fail/shutdown-related method surface. |
| src/xrpld/overlay/detail/PeerImp.cpp | Reworks stop/send/close + EOF/SSL shutdown handling and timer helpers. |
| src/xrpld/overlay/detail/ConnectAttempt.h | Simplifies ConnectAttempt interface/state and removes step-timeout machinery. |
| src/xrpld/overlay/detail/ConnectAttempt.cpp | Reverts connection attempt lifecycle toward simpler close + single timer; adjusts response processing and logging. |
| include/xrpl/server/detail/Door.h | Uses protocol.contains(...) for protocol detection. |
Comments suppressed due to low confidence (6)
src/xrpld/overlay/detail/PeerImp.cpp:813
PeerImp::onShutdowntreats a successful SSL shutdown (ec == 0) as an error ("expected error condition") and only acceptsboost::asio::error::eofas the success case. This is inconsistent with other shutdown handlers in the repo (e.g.SSLHTTPPeer::onShutdown) and can produce false error logs / incorrect failure handling whenasync_shutdowncompletes successfully. Consider treating both!ecandec == boost::asio::error::eofas normal completion, and only logging/failing for other errors (withoperation_abortedhandled separately if needed).
PeerImp::onShutdown(error_code ec)
{
cancelTimer();
// If we don't get eof then something went wrong
if (!ec)
{
JLOG(journal_.error()) << "onShutdown: expected error condition";
close();
return;
}
if (ec != boost::asio::error::eof)
{
fail("onShutdown", ec);
return;
}
close();
src/xrpld/overlay/detail/PeerImp.cpp:631
PeerImp::closeonly cancelstimer_whensocket_.is_open(). Ifclose()(orstop()/fail()) is invoked after the socket has already been closed, the pendingtimer_.async_waitwill remain scheduled and keep thePeerImpalive until it fires (up tokPeerTimerInterval). Consider cancelling the timer unconditionally (viacancelTimer()) even when the socket is already closed.
PeerImp::close()
{
XRPL_ASSERT(strand_.running_in_this_thread(), "xrpl::PeerImp::close : strand in this thread");
if (socket_.is_open())
{
detaching_ = true; // DEPRECATED
try
{
timer_.cancel();
socket_.close();
src/xrpld/overlay/detail/ConnectAttempt.cpp:108
ConnectAttempt::runno longer posts to the strand and no longer arms a timeout before startingasync_connect. This makesrun()not thread-safe (callers can invoke it off-strand) and can allow the TCP connect to hang indefinitely (nosetTimer()until afteronConnect). Consider restoring therunning_in_this_thread()gate and starting the timer beforeasync_connect.
This issue also appears in the following locations of the same file:
- line 280
- line 329
void
ConnectAttempt::run()
{
stream_.next_layer().async_connect(
remoteEndpoint_,
boost::asio::bind_executor(
strand_,
std::bind(&ConnectAttempt::onConnect, shared_from_this(), std::placeholders::_1)));
}
src/xrpld/overlay/detail/ConnectAttempt.cpp:300
- After a successful HTTP write,
ConnectAttempt::onWritestartshttp::async_readwithout arming a timer. This means the HTTP read step can block indefinitely if the peer stops responding. Consider callingsetTimer()before starting theasync_read(and cancelling it inonRead).
void
ConnectAttempt::onWrite(error_code ec)
{
cancelTimer();
if (!socket_.is_open())
return;
if (ec == boost::asio::error::operation_aborted)
return;
if (ec)
{
fail("onWrite", ec);
return;
}
boost::beast::http::async_read(
stream_,
readBuf_,
response_,
boost::asio::bind_executor(
strand_,
std::bind(&ConnectAttempt::onRead, shared_from_this(), std::placeholders::_1)));
}
src/xrpld/overlay/detail/ConnectAttempt.cpp:345
ConnectAttempt::onShutdowntreats a successful SSL shutdown (ec == 0) as an error and only acceptsboost::asio::error::eofas success. That can lead to false error logs and unnecessary failures when the TLS shutdown handshake completes normally. Consider treating!ecandec == boost::asio::error::eofas normal completion, and failing/logging only other errors (withoperation_abortedhandled separately if applicable).
void
ConnectAttempt::onShutdown(error_code ec)
{
cancelTimer();
if (!ec)
{
JLOG(journal_.error()) << "onShutdown: expected error condition";
close();
return;
}
if (ec != boost::asio::error::eof)
{
fail("onShutdown", ec);
return;
}
close();
}
src/xrpld/overlay/detail/ConnectAttempt.h:101
parseEndpointusesstd::istringstream, but this header doesn't include<sstream>directly, relying on transitive includes (currently viaApplication.h->PropertyStream.h). Adding the direct include would avoid fragile header-order dependencies.
template <class = void>
static boost::asio::ip::tcp::endpoint
parseEndpoint(std::string const& s, boost::system::error_code& ec)
{
beast::IP::Endpoint bep;
std::istringstream is(s);
is >> bep;
if (is.fail())
{
ec = boost::system::errc::make_error_code(boost::system::errc::invalid_argument);
return boost::asio::ip::tcp::endpoint{};
}
return beast::IPAddressConversion::toAsioEndpoint(bep);
}
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## develop #7296 +/- ##
=========================================
+ Coverage 82.1% 82.3% +0.1%
=========================================
Files 1011 1011
Lines 76343 76194 -149
Branches 7417 7341 -76
=========================================
- Hits 62691 62681 -10
+ Misses 13652 13513 -139
🚀 New features to boost your workflow:
|
bthomee
left a comment
There was a problem hiding this comment.
I didn't get to reviewing it all now, but at least can give you some feedback.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 5 out of 5 changed files in this pull request and generated 6 comments.
Comments suppressed due to low confidence (1)
src/xrpld/overlay/detail/PeerImp.cpp:1053
- When gracefulClose_ is set and the sendQueue_ becomes empty, onWriteMessage starts stream_.async_shutdown() directly but does not arm any shutdown timeout. If the peer never completes the TLS close_notify handshake, this async_shutdown can hang indefinitely. Prefer routing through gracefulClose() (or arming a shutdown timer here) so shutdown has a bounded duration.
if (gracefulClose_)
{
stream_.async_shutdown(bind_executor(
strand_, std::bind(&PeerImp::onShutdown, shared_from_this(), std::placeholders::_1)));
return;
Reverts the following commits:
Performed as a manual revert against current HEAD so that identifier renames landed by subsequent refactors (snake_case to camelCase methods, fee* to kFee* constants, scoped enums, etc.) are preserved.
High Level Overview of Change
Context of Change
API Impact
libxrplchange (any change that may affectlibxrplor dependents oflibxrpl)