What changed, and why it matters
This commit fixes a resource leak in Electrum's mobile-style QML user interface. If a user closed the wallet unlock dialog without actually unlocking a wallet, a hidden 'LoadingWalletDialog' would keep running in the background. Its internal signal connections would pile up and never be cleaned up, which could gradually slow down or destabilize the app. The fix explicitly destroys the dialog when it was never shown, so its cleanup code runs.
Apply the patch. It is a low-risk UI cleanup fix. Users on the QML/mobile build should update to avoid gradual performance degradation or instability when repeatedly opening and cancelling wallet unlock.
Security signals we found
Resource leak / object lifecycle bug in QML dialog
Accumulation of stale signal connections and callbacks
UI-only fix in the QML (mobile) interface, not the core wallet logic
No cryptographic, network, or transaction-handling code changed
Evidence from the diff
In electrum/gui/qml/components/LoadingWalletDialog.qml, the dialog listens for Daemon.loading to become false and then calls dialog.close(). If the dialog was never made visible, QML’s onClosed handler does not fire, so any Connections and callbacks registered by the dialog remain active. The patch checks dialog.visible first: if visible it closes normally; otherwise it schedules dialog.destroy() via Qt.callLater so the object and its connections are disposed of. This prevents accumulation of stale signal connections and leaked callbacks.
Changed components
electrum/gui/qml/components/LoadingWalletDialog.qmlInspect captured patch +7 / −1
diff --git a/electrum/gui/qml/components/LoadingWalletDialog.qml b/electrum/gui/qml/components/LoadingWalletDialog.qml
index 2969cdc..a680a8e 100644
--- a/electrum/gui/qml/components/LoadingWalletDialog.qml
+++ b/electrum/gui/qml/components/LoadingWalletDialog.qml
@@ -44,7 +44,13 @@ ElDialog {
console.log('daemon loading ' + Daemon.loading)
if (!Daemon.loading) {
showTimer.stop()
- dialog.close()
+ if (dialog.visible) {
+ dialog.close()
+ } else {
+ // if the dialog wasn't visible its onClosed callbacks don't get called, so it
+ // needs to be destroyed manually
+ Qt.callLater(function() { dialog.destroy() })
+ }
}
}
}
Why this scored 23/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.