From 1fb6dc44d99ab879925e4647dbd8d052d5183e91 Mon Sep 17 00:00:00 2001 From: DanS Date: Tue, 9 Jun 2026 21:25:22 -0500 Subject: [PATCH] fix(node): fail the localhost connect probe fast (8s, not 30s) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The connection probe (getinfo) used a 30s request timeout, so when something on the local RPC port accepts TCP but never answers — a daemon still loading the block index, or a wedged/foreign occupant — every attempt blocked the full 30s before the wallet could retry or update its status. That is the "stuck, timing out every 30s" behaviour users hit. A healthy local daemon answers getinfo in milliseconds, and a warming one returns -28 just as fast, so a long hang on localhost only ever means trouble. Probe localhost with an 8s timeout (remote/TLS keeps the 30s budget). The per-call override restores the persistent 30s afterwards, so normal RPC calls that legitimately take longer are unaffected — only the probe fails faster, so the wallet retries promptly and reflects "initializing" / recovery within seconds of the daemon becoming ready. Co-Authored-By: Claude Opus 4.8 --- src/rpc/rpc_client.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/rpc/rpc_client.cpp b/src/rpc/rpc_client.cpp index 0a2e7b1..18f2fdf 100644 --- a/src/rpc/rpc_client.cpp +++ b/src/rpc/rpc_client.cpp @@ -189,9 +189,14 @@ bool RPCClient::connect(const std::string& host, const std::string& port, const long connectTimeout = Connection::isLocalHost(host) ? 2L : 10L; curl_easy_setopt(impl_->curl, CURLOPT_CONNECTTIMEOUT, connectTimeout); - // Test connection with getinfo + // Test connection with getinfo. Use a SHORT timeout for the probe on localhost: a healthy + // local daemon answers in milliseconds and a warming one returns -28 just as fast, so a long + // hang means a wedged/loading occupant — no point blocking the full 30s before we retry and + // update the UI. (call(timeoutSec) restores the persistent 30s afterwards, so normal RPC calls + // that legitimately take longer are unaffected.) Remote/TLS daemons keep the full budget. + const long probeTimeout = Connection::isLocalHost(host) ? 8L : 30L; try { - json result = call("getinfo"); + json result = call("getinfo", json::array(), probeTimeout); if (result.contains("version")) { connected_ = true; warming_up_ = false;