From afb0843b381f41a307c271e53517510b11dc2868 Mon Sep 17 00:00:00 2001 From: Meshari Date: Fri, 30 Jan 2026 15:48:08 +0000 Subject: [PATCH 1/2] Fix TorControlSocket shutdown hang by adding timeout --- src/tor/TorControl.cpp | 18 +++++++++++++++--- src/tor/TorControlSocket.cpp | 19 ++++++++++++++----- 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/src/tor/TorControl.cpp b/src/tor/TorControl.cpp index 106244b01..3e2bdd4ec 100644 --- a/src/tor/TorControl.cpp +++ b/src/tor/TorControl.cpp @@ -535,16 +535,28 @@ void TorControl::shutdown() void TorControl::shutdownSync() { + if (!hasOwnership()) { RsWarn() << "torctrl: Ignoring shutdown command for a tor instance I don't own"; return; } - shutdown(); - while (mSocket->moretowrite(0)) + + // Add timeout to prevent infinite wait + int timeout_cnt = 0; + const int MAX_WAIT_ITERATIONS = 50; // 5 seconds max (50 * 100ms) + + while (mSocket->moretowrite(0) && timeout_cnt < MAX_WAIT_ITERATIONS) { std::this_thread::sleep_for(std::chrono::milliseconds(100)); - + timeout_cnt++; + } + + if (timeout_count >= MAX_WAIT_ITERATIONS) { + RsWarn() << "torctrl: Timeout waiting for socket to flush during shutdown, forcing close"; + } + mSocket->close(); + } void TorControl::statusEvent(int /* code */, const ByteArray &data) diff --git a/src/tor/TorControlSocket.cpp b/src/tor/TorControlSocket.cpp index ccf74b344..6446adfe8 100644 --- a/src/tor/TorControlSocket.cpp +++ b/src/tor/TorControlSocket.cpp @@ -126,6 +126,10 @@ ByteArray TorControlSocket::readline(int s) void TorControlSocket::process() { + + int empty_line_cnt = 0; + const int MAX_EMPTY_RETRIES = 20; + for (;;) { if (!moretoread(0)) return; @@ -134,10 +138,15 @@ void TorControlSocket::process() if(line.empty()) // This happens when the incoming buffer isn't empty yet doesn't have a full line already. { + if (++empty_line_cnt > MAX_EMPTY_RETRIES || shouldStop()) { + return; // Give up after timeout or stop request + } std::this_thread::sleep_for(std::chrono::milliseconds(50)); continue; } + empty_line_cnt = 0; // reset + if (!line.endsWith(ByteArray("\r\n"))) { setError("Invalid control message syntax"); return; @@ -225,12 +234,12 @@ void TorControlSocket::process() int TorControlSocket::tick() { bool rw = RsTcpSocket::tick(); - if(moretoread(0)) process(); - + if(!rw) - std::this_thread::sleep_for(std::chrono::milliseconds(1000)); // temporisation when nothing happens - - return 0; // not sure about what we should return here. + std::this_thread::sleep_for(std::chrono::milliseconds(50)); // Much shorter sleep + + return 0; } + From a36fa8f35fb26db98ebdc7d48f3072a1b33194f5 Mon Sep 17 00:00:00 2001 From: Meshari Date: Fri, 30 Jan 2026 16:08:14 +0000 Subject: [PATCH 2/2] Variable typo --- src/tor/TorControl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tor/TorControl.cpp b/src/tor/TorControl.cpp index 3e2bdd4ec..ed4a3f417 100644 --- a/src/tor/TorControl.cpp +++ b/src/tor/TorControl.cpp @@ -551,7 +551,7 @@ void TorControl::shutdownSync() timeout_cnt++; } - if (timeout_count >= MAX_WAIT_ITERATIONS) { + if (timeout_cnt >= MAX_WAIT_ITERATIONS) { RsWarn() << "torctrl: Timeout waiting for socket to flush during shutdown, forcing close"; }