-
Notifications
You must be signed in to change notification settings - Fork 37.7k
wallet: Call load handlers without cs_wallet locked #22868
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
1ba170e
to
2c87f99
Compare
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. ConflictsNo conflicts as of last run. |
Why this change is safe? |
@hebasto what is the concern? The lock can be acquired inside the load handler. This change also avoids recursive locks on |
This does seem probably safe, but it would save reviewers some effort to know when the lock was added, when it stopped being necessary, and the specific reason why it was necessary whenever it was needed (for example whether it was avoiding deadlocks or asserts by acquiring recursive locks in a consistent order, or whether it was avoiding race condition.) This information could go in the PR description. One concern might be that one of the |
My bad for not writing this, I went thru history before making the change, will redo and update this.
Would be bad to lock one |
@ryanofsky see https://github.com/bitcoin/bitcoin/pull/11634/files#r227725517 for when the lock was added and @practicalswift submitted a similar change #14560 but @MarcoFalke rejected it. |
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 2c87f99. It seems safe to remove this lock because it look like it was only added by accident in #11634 to try to satisfy lock annotations, even though it was never really needed to satisfy lock annotations even according to the thread there https://github.com/bitcoin/bitcoin/pull/11634/files#r227725517. (EDIT: lock was not added by accident, it was needed but was always broader than it needed to be and it became unnecessary after a recursive lock was added in #20773)
⬆️ I think above information would be helpful to add to PR description because otherwise this PR seems like a random change.
After this PR, I think there are no more cases where cs_wallet
and wallets_mutex
are locked at the same time so there is no required lock ordering between them. But in the future, GUI code could do arbitrary things in its wallet_load_fns
handler, and maybe it will call a wallet function and lock cs_wallet
in one. In that case the lock order would be wallets_mutex
first then cs_wallet
second. It may be good to state some intended lock ordering, maybe adding a code comment to WalletContext::wallets_mutex
like "It is unsafe to lock this after locking a CWallet::cs_wallet
mutex because this could introduce inconsistent lock ordering and cause deadlocks."
One concern might be that one of the
wallet_load_fns
callbacks could call a wallet method and acquire cs_wallet mutex after context.wallets_mutex, and maybe this would be in inconsistent order.Would be bad to lock one
cs_wallet
afterwallets_mutex
?
If there is any thread locking wallets_mutex
after cs_wallet
then it would be bad, but if not, then it's fine.
In master that already happens but works because
cs_wallet
is recursive. Couldn't find more cases of cs_wallet -> wallets_mutex lock order.
I don't think this matters because recursive locks are no-ops. It a thread locks mutex A, then locks mutex B, then recursively locks mutex A again, then the recursive lock isn't doing anything, and the lock order is still A before B.
@ryanofsky thanks! You might want to see bitcoin-core/gui@c09fd3a, it needs this change otherwise it deadlocks. |
Thanks! That also looks like a good change. Is there a PR or issue this is all a part of? |
@ryanofsky yes, bitcoin-core/gui#417 Edit: I guess I have to rebase. |
2c87f99
to
7850d33
Compare
Rebased due to trivial conflict with #23123. |
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 7850d33 with caveats from #22868 (review) that I'm not 100% sure this won't cause deadlocks now or in the future, but do think this seems safe and is probably a good simplification. Also I think the PR description is lacking essential information like why it is safe to remove the lock and how long it's been unnecessary.
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.
Looks correct to me, utACK 7850d33
Agree with Russ though, definitely think the PR description needs updating.
7850d33
to
c34d934
Compare
This is already the case and it is where the GUI models are filled. @meshcollider @ryanofsky updated OP, added Also rebased. |
Co-authored-by: Russell Yanofsky <russ@yanofsky.org>
c34d934
to
f13a22a
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.
re-utACK f13a22a
PR description doesn't seem totally accurate, from #22868 (comment)
If my understanding of https://github.com/bitcoin/bitcoin/pull/11634/files#r227725517 is correct, then the lock was not added to satsify TSAN but was added to satisfy clang annotations. I think you could summarize this by saying that this LOCK(cs_wallet) was correctly added in #11634, but it became no longer unnecessary after #20773 when code requiring the lock was moved to the new Also it now seems like the motivation for this change is not just removing an unnecessary lock, but reversing the 1. cs_wallet 2. wallets_mutex lock order so it can now be 1. wallets_mutex 2. cs_wallet, because upcoming GUI PR bitcoin-core/gui#417 needs this |
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 f13a22a. Only change since last review is adding a lock order comment
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 f13a22a
@@ -34,6 +34,8 @@ using LoadWalletFn = std::function<void(std::unique_ptr<interfaces::Wallet> wall | |||
struct WalletContext { | |||
interfaces::Chain* chain{nullptr}; | |||
ArgsManager* args{nullptr}; // Currently a raw pointer because the memory is not managed by this struct | |||
// It is unsafe to lock this after locking a CWallet::cs_wallet mutex because | |||
// this could introduce inconsistent lock ordering and cause deadlocks. |
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.
Haven't tried, but would there be any point in using EXCLUDES
/ LOCKS_EXCLUDED
(or REQUIRES(!mutex)
with -Wthread-safety-negative
) annotations to enforce this?
f13a22a wallet: Call load handlers without cs_wallet locked (João Barbosa) Pull request description: Don't have `cs_wallet` locked while calling each `context.wallet_load_fns`. A load handler can always lock `cs_wallet` if needed. The lock was added in 1c7e25d to satisfy TSAN. With 44c430f most of the code requiring the lock is in `CWallet::AttachChain`. A comment is added to warn about wallets_mutex and cs_wallet lock ordering. ACKs for top commit: meshcollider: re-utACK f13a22a ryanofsky: Code review ACK f13a22a. Only change since last review is adding a lock order comment jonatack: ACK f13a22a Tree-SHA512: d51976c3aae4bebc2d1997c88edff712d21fc5523801f5614062a10f826e164579973aeb1981bb1cbc243ecff6af3250362f544c02a79e5d135cbbca1704be62
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.
Ok
Don't have
cs_wallet
locked while calling eachcontext.wallet_load_fns
. A load handler can always lockcs_wallet
if needed.The lock was added in 1c7e25d to satisfy TSAN. With 44c430f most of the code requiring the lock is in
CWallet::AttachChain
. A comment is added to warn about wallets_mutex and cs_wallet lock ordering.