Fixes #689
Summary
If you open a wallet and send a shutdown signal during that process, you’ll get a segfault when the wallet finishes opening. That’s because the WalletController
object gets deleted manually in bitcoin.cpp during shutdown, but copies of the pointer (and pointers to child objects) are dangling in various places and are accessed in queued events after the deletion.
Details
The issue in #689 is caused by the following sequence of events:
- Wallet open modal dialog is shown and worker thread does the actual work.
- Every 200ms, the main event loop checks to see if a shutdown has been requested, but only if a modal is not being shown.
- Request a shutdown while the modal window is shown.
- The wallet open process completes, the modal window is dismissed, and various
finish
signals are sent. - During handling of one of the
finish
signals,qApp->processEvents()
is called, which causes the main event loop to detect the shutdown (now that the modal window has been dismissed). TheWalletController
and all theWalletModel
s are deleted. - Control returns to the
finish
method, which eventually tries to send a signal from a wallet model, but it’s been deleted already (and the signal is sent from a now-dangling pointer).
The simplest fix for that is to change the qApp->processEvents()
into a QueuedConnection
call. (The `qApp->processEvents() was a workaround to get the GUI to scroll to the last item in a list that just got added, and this is just a safer way of doing that).
However, once that segfault is fixed, another segfault occurs due to some queued wallet events happening after the wallet controller object is deleted here:
Since m_wallet_controller
is a copy of that pointer in bitcoingui.cpp
, it’s now dangling and if(null)
checks won’t work correctly. For instance, this line:
sets up a QueuedConnection
to setCurrentWallet
, but by the time control reaches that method (one event cycle after shutdown deleted m_wallet_controller
in bitcoin.cpp
), the underlying objects have been destroyed (but the pointers are still dangling).
Ideally, we’d use a QPointer
or std::shared_ptr / std::weak_ptr
s for these, but the changes would be more involved.
This is a minimal fix for the issues. Just set m_wallet_controller
to nullptr
in bitcoingui.cpp
, check its value in a couple places, and avoid a use of qApp->processEvents
.