-
Notifications
You must be signed in to change notification settings - Fork 37.7k
wallet: Avoid locking cs_wallet recursively #19833
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. ConflictsReviewers, this pull request conflicts with the following ones:
If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first. |
ec3f4bf
to
d306298
Compare
Concept ACK. |
d306298
to
a98d192
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK 9c5a28c "wallet: GetLabelAddresses requires cs_wallet lock "
ACK 7a138a8 "wallet: AddWalletDescriptor requires cs_wallet lock"
Approach NACK a98d192 "wallet: GetBalance requires cs_wallet lock"
Placing LOCK()
macros in member functions of a class that implements an interface is not a good idea. When CWallet::cs_wallet
actually transits from RecurviseMutex
to Mutex
we will be forced to guard all such functions with negative assertions EXCLUSIVE_LOCKS_REQUIRED(!m_wallet->cs_wallet)
. But they won't work as they are placed not in a header file.
Seems unnecessary no? Locking an already locked |
There are already LOCK(cs_wallet) in the interface cpp file. How is the new one any different and how would it make it any harder. Also, I am not sure if we really want to annotate extensively with negative lock annotations. Has there been a conceptual discussion about this? |
Yes, it does. In run time.
Actually moving implementation class declaration into a header will help.
Yes, there are. Unfortunately.
You are correct. But it seems premature until transit from |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK a98d192, convinced after discussion, tested on Linux Mint 20 (x86_64).
I don't understand what you mean, please elaborate. |
I don't think you could use EXCLUSIVE_LOCKS_REQUIRED(!m_wallet->cs_wallet) in the interfaces::WalletImpl class, for the same reason you couldn't use EXCLUSIVE_LOCKS_REQUIRED(!pwallet->cs_wallet) on RPC methods, because method callers can't know which wallet object the wallet pointer points to, so couldn't provably meet the requirements. To make cs_wallet non-recursive, you I think you just need to make a blanket assumption that cs_wallet will not held when calling RPC methods or interfaces::Wallet* methods, and it won't be possible to use locking annotations in a meaningful way. |
The reason the implementation class is not in a header is that implementation class methods are never called directly. They are only called through the interface, and the interface is only called by the GUI. I don't think there's a way to make GUI aware of cs_wallet and be able to satisfy assertions about whether it is locked or unlocked. |
We could use
Mind looking into this branch: https://github.com/hebasto/bitcoin/commits/pr19833-0831-demo ? |
a98d192
to
fa2cf36
Compare
@hebasto rebased to have a fresh build, mind taking a 2nd look? @meshcollider ping. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, but another rebasing seems required :)
I think this pull is an improvement of the current CWallet
interface design. In the future it could be re-designed with the concurrency in mind, i.e., without public access to mutexes etc.
src/interfaces/wallet.cpp
Outdated
@@ -348,6 +348,7 @@ class WalletImpl : public Wallet | |||
} | |||
WalletBalances getBalances() override | |||
{ | |||
LOCK(m_wallet->cs_wallet); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could the lock be bounded to GetBalance
only?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
WITH_LOCK?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
WITH_LOCK?
That is my thought.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's no big deal for now. I'll do it it I have to update.
fa2cf36
to
97dbdcd
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK 97dbdcd, I have reviewed the code and it looks OK, I agree it can be merged.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code review ACK 97dbdcd. This makes locking code less confusing without changing behavior and should make it easier to switch to a non-recursive lock.
hebasto's approach hebasto/bitcoin@pr19833-0831-demo
(commits) to use lock annotations to prevent the gui from calling wallet methods while holding cs_wallet could be an interesting followup. Though if there are cases where wallet is locking cs_wallet, and then making a gui callback which calls interfaces::Wallet methods, it might be an indication that the notification API is too low level, and more code should be moved from the GUI to the wallet, so code can run entirely in the wallet, instead of calling out of the wallet to the gui then back into the wallet.
A friendly reminder to rebase :) Happy to re-ACK then. |
No change in behavior, the lock is already held at call sites.
No change in behavior, the lock is already held at call sites.
97dbdcd
to
5fabde6
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code review ACK 97dbdcd. I didn't look to see what previously discussed followups may be still applicable, but the current version of this does nicely cleans up a few locks and looks good
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK 5fabde6, I have reviewed the code and it looks OK, I agree it can be merged.
5fabde6 wallet: AddWalletDescriptor requires cs_wallet lock (João Barbosa) 32d036e wallet: GetLabelAddresses requires cs_wallet lock (João Barbosa) Pull request description: This is another small change towards non recursive wallet lock. ACKs for top commit: hebasto: ACK 5fabde6, I have reviewed the code and it looks OK, I agree it can be merged. Tree-SHA512: 00506f0159c56854a171e58a451db8dd9b9f735039697b1cf2ca7f54de61fb51cc1e5eff42265233e041b4b1bfd29c2247496dc4456578e1a23c323bdec2901b
This is another small change towards non recursive wallet lock.