Skip to content

Commit 2fdb559

Browse files
authored
BugFix: fix the issue of the client-side socket fd cannot be recycled in a timely manner when using fiber connection pool, causing the number of close-wait to increase. (#108)
1 parent b1a67e0 commit 2fdb559

3 files changed

Lines changed: 27 additions & 5 deletions

File tree

trpc/runtime/iomodel/reactor/fiber/fiber_connection.cc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,12 @@ void FiberConnection::QueueCleanupCallbackCheck() {
352352
read_mostly_.seldomly_used->error_events.load(std::memory_order_relaxed) == 0) {
353353
// Consider queue a call to `OnCleanup()` then.
354354
if (!read_mostly_.seldomly_used->cleanup_queued.exchange(true, std::memory_order_release)) {
355+
{
356+
std::scoped_lock<std::mutex> _(mutex_);
357+
// Set the connection unavailability status flag in advance to make read/write tasks retreat in advance,
358+
// reducing the conflict of Cleanup callback locks.
359+
conn_unavailable_ = true;
360+
}
355361
// No need to take a reference to us, `OnCleanup()` has not been called.
356362
GetReactor()->SubmitTask([this] {
357363
// The load below acts as a fence (paired with `exchange` above). (But

trpc/runtime/iomodel/reactor/fiber/fiber_connection.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,12 @@ class alignas(hardware_destructive_interference_size) FiberConnection : public C
118118

119119
std::atomic<std::size_t> restart_read_count_{0}, restart_write_count_{0};
120120

121+
// Connection closing cleanup and connection sending/receiving mutex lock, to protect connection cleanup and network
122+
// data transmission/reception thread safety.
123+
std::mutex mutex_;
124+
// Connection unavailability status flag.
125+
bool conn_unavailable_{false};
126+
121127
private:
122128
void SuppressReadAndClearReadEvent();
123129
void SuppressAndClearWriteEvent();

trpc/runtime/iomodel/reactor/fiber/fiber_tcp_connection.cc

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,6 @@ FiberTcpConnection::FiberTcpConnection(Reactor* reactor, const Socket& socket)
3131
}
3232

3333
FiberTcpConnection::~FiberTcpConnection() {
34-
// Requirements: destroy IO-handler before close socket.
35-
GetIoHandler()->Destroy();
36-
socket_.Close();
37-
3834
TRPC_LOG_DEBUG("~FiberTcpConnection fd:" << socket_.GetFd() << ", conn_id:" << this->GetConnId());
3935
TRPC_ASSERT(!socket_.IsValid());
4036
}
@@ -116,7 +112,15 @@ int FiberTcpConnection::Send(IoMessage&& msg) {
116112
}
117113

118114
constexpr auto kMaximumBytesPerCall = 1048576;
115+
// External calls to the Send method may conflict with Socket closing concurrently, so a lock is added here for
116+
// protection.
117+
std::unique_lock<std::mutex> lock(mutex_);
118+
// If the connection is unavailable, return an error directly.
119+
if (conn_unavailable_) {
120+
return -1;
121+
}
119122
auto flush_status = FlushWritingBuffer(kMaximumBytesPerCall);
123+
lock.unlock();
120124
if (TRPC_LIKELY(flush_status == FlushStatus::kFlushed)) {
121125
return 0;
122126
} else if (flush_status == FlushStatus::kSystemBufferSaturated || flush_status == FlushStatus::kQuotaExceeded) {
@@ -370,7 +374,13 @@ void FiberTcpConnection::OnCleanup(CleanupReason reason) {
370374

371375
writing_buffers_.Stop();
372376

373-
// For multi-threads-safety, move "socket_.Close()" to ~FiberTcpConnection();
377+
{
378+
std::scoped_lock<std::mutex> _(mutex_);
379+
conn_unavailable_ = true;
380+
// Requirements: destroy IO-handler before close socket.
381+
GetIoHandler()->Destroy();
382+
socket_.Close();
383+
}
374384
}
375385

376386
IoHandler::HandshakeStatus FiberTcpConnection::DoHandshake(bool from_on_readable) {

0 commit comments

Comments
 (0)