Skip to content

Commit e9ef27d

Browse files
committed
Fix event loop freeze: replace blocking stratum write with async queue
send_response() used synchronous boost::asio::write() on the ioc thread. When a miner's TCP receive buffer was full (network issue), this blocked the entire single-threaded event loop — no timers, P2P, or watchdog could fire until the kernel TCP retransmission timed out (~15 min). Replace with async_write + deque write queue pattern. Each send_response() pushes to the queue and kicks do_write() which chains async_write calls. On error, the socket is closed and the queue cleared. Also adds runtime LevelDB pruning: batch-delete shares evicted by clean_tracker's drop-tails step, matching p2pool's tracker.removed.watch pattern that propagates in-memory removal to disk storage.
1 parent 5ce68e6 commit e9ef27d

2 files changed

Lines changed: 29 additions & 2 deletions

File tree

src/core/stratum_server.cpp

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1085,12 +1085,36 @@ void StratumSession::send_response(const nlohmann::json& response)
10851085
{
10861086
try {
10871087
std::string message = response.dump() + "\n";
1088-
boost::asio::write(socket_, boost::asio::buffer(message));
1088+
write_queue_.push_back(std::move(message));
1089+
if (!writing_)
1090+
do_write();
10891091
} catch (const std::exception& e) {
1090-
LOG_ERROR << "[Stratum] Error sending response: " << e.what();
1092+
LOG_ERROR << "[Stratum] Error queueing response: " << e.what();
10911093
}
10921094
}
10931095

1096+
void StratumSession::do_write()
1097+
{
1098+
if (write_queue_.empty() || !socket_.is_open()) {
1099+
writing_ = false;
1100+
return;
1101+
}
1102+
writing_ = true;
1103+
auto self = shared_from_this();
1104+
boost::asio::async_write(socket_, boost::asio::buffer(write_queue_.front()),
1105+
[this, self](boost::system::error_code ec, std::size_t /*bytes*/) {
1106+
if (ec) {
1107+
LOG_ERROR << "[Stratum] Error sending response: " << ec.message();
1108+
write_queue_.clear();
1109+
writing_ = false;
1110+
try { socket_.close(); } catch (...) {}
1111+
return;
1112+
}
1113+
write_queue_.pop_front();
1114+
do_write();
1115+
});
1116+
}
1117+
10941118
void StratumSession::send_error(int code, const std::string& message, const nlohmann::json& request_id)
10951119
{
10961120
nlohmann::json response;

src/core/stratum_server.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@ class StratumSession : public std::enable_shared_from_this<StratumSession>
8787
{
8888
tcp::socket socket_;
8989
boost::asio::streambuf buffer_;
90+
std::deque<std::string> write_queue_; // async write queue (non-blocking)
91+
bool writing_ = false; // true while an async_write is in flight
9092
std::shared_ptr<MiningInterface> mining_interface_;
9193
StratumServer* server_ = nullptr; // back-pointer for RateMonitor recording
9294
std::string subscription_id_;
@@ -192,6 +194,7 @@ class StratumSession : public std::enable_shared_from_this<StratumSession>
192194
nlohmann::json handle_suggest_difficulty(const nlohmann::json& params, const nlohmann::json& request_id);
193195

194196
void send_response(const nlohmann::json& response);
197+
void do_write(); // drain the async write queue
195198
void send_error(int code, const std::string& message, const nlohmann::json& request_id);
196199
void send_set_difficulty(double difficulty);
197200
void send_set_extranonce(const std::string& extranonce1, int extranonce2_size);

0 commit comments

Comments
 (0)