fix(rpc): detect mid-session disconnects and stop blocking the UI thread
The connection state machine never tore down on a lost connection: refresh-loop RPC errors were swallowed, rpc_->isConnected() stayed true after a daemon crash/restart/socket drop, and the UI showed stale balances with no reconnect. Several operations also ran synchronous curl straight from ImGui handlers. - Add handleLostConnection(): after N consecutive cycles where BOTH core RPCs fail (warmup excluded, so no reconnect loop), disconnect so update()'s reconnect branch re-enters tryConnect(). - Move banPeer/unbanPeer/clearBans and key export/import onto the worker thread (import requests a rescan that could freeze the UI for the curl timeout). - Run the block-info dialog's two chained RPCs on the worker thread (+ guard the getblockhash result type). - Detect daemon warmup via the JSON-RPC -28 code (new RpcError carrying the code; message text preserved so 401/warmup string-matching is unaffected), and widen CONNECTTIMEOUT to 10s for remote/TLS hosts (2s localhost). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
#include "block_info_dialog.h"
|
||||
#include "../../app.h"
|
||||
#include "../../rpc/rpc_client.h"
|
||||
#include "../../rpc/rpc_worker.h"
|
||||
#include "../../util/i18n.h"
|
||||
#include "../notifications.h"
|
||||
#include "../schema/ui_schema.h"
|
||||
@@ -124,14 +125,31 @@ void BlockInfoDialog::render(App* app)
|
||||
}
|
||||
|
||||
if (material::StyledButton(TR("block_get_info"), ImVec2(0,0), S.resolveFont(closeBtn.font))) {
|
||||
if (rpc && rpc->isConnected()) {
|
||||
if (rpc && rpc->isConnected() && app->worker()) {
|
||||
s_loading = true;
|
||||
s_error.clear();
|
||||
s_has_data = false;
|
||||
s_pending_app = app;
|
||||
|
||||
// Use getBlock(height) which uses UnifiedCallback
|
||||
rpc->getBlock(s_height, handleBlockResponseUnified);
|
||||
|
||||
// Run the two chained RPCs (getblockhash → getblock) on the worker thread;
|
||||
// doing them inline froze the UI for two round-trips. Guard the hash type.
|
||||
int height = s_height;
|
||||
app->worker()->post([rpc, height]() -> rpc::RPCWorker::MainCb {
|
||||
json block;
|
||||
std::string error;
|
||||
try {
|
||||
rpc::RPCClient::TraceScope trace("Explorer / Block info");
|
||||
auto hashResult = rpc->call("getblockhash", {height});
|
||||
if (!hashResult.is_string()) {
|
||||
error = "unexpected getblockhash result";
|
||||
} else {
|
||||
block = rpc->call("getblock", {hashResult.get<std::string>()});
|
||||
}
|
||||
} catch (const std::exception& e) {
|
||||
error = e.what();
|
||||
}
|
||||
return [block, error]() { handleBlockResponseUnified(block, error); };
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user