diff --git a/src/tor/TorControl.cpp b/src/tor/TorControl.cpp index 106244b01..ed4a3f417 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_cnt >= 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; } +