Skip to content

Conversation

promag
Copy link
Contributor

@promag promag commented Aug 29, 2020

This is another small change towards non recursive wallet lock.

@DrahtBot
Copy link
Contributor

DrahtBot commented Aug 29, 2020

The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

Conflicts

Reviewers, this pull request conflicts with the following ones:

  • #22341 (rpc: add getxpub by Sjors)
  • #20205 (wallet: Properly support a wallet id by achow101)
  • #19602 (wallet: Migrate legacy wallets to descriptor wallets by achow101)

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.

@hebasto
Copy link
Member

hebasto commented Aug 30, 2020

Concept ACK.

Copy link
Member

@hebasto hebasto left a 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.

@promag
Copy link
Contributor Author

promag commented Aug 31, 2020

we will be forced to guard all such functions with negative assertions EXCLUSIVE_LOCKS_REQUIRED(!m_wallet->cs_wallet)

Seems unnecessary no? Locking an already locked Mutex fails. If you really want static analysis then we could add a new method in the private implementation just to add the annotation?

@maflcko
Copy link
Member

maflcko commented Aug 31, 2020

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.

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?

@hebasto
Copy link
Member

hebasto commented Aug 31, 2020

@promag

we will be forced to guard all such functions with negative assertions EXCLUSIVE_LOCKS_REQUIRED(!m_wallet->cs_wallet)

Seems unnecessary no? Locking an already locked Mutex fails.

Yes, it does. In run time.

If you really want static analysis then we could add a new method in the private implementation just to add the annotation?

Actually moving implementation class declaration into a header will help.

@MarcoFalke

There are already LOCK(cs_wallet) in the interface cpp file.

Yes, there are. Unfortunately.

Also, I am not sure if we really want to annotate extensively with negative lock annotations. Has there been a conceptual discussion about this?

You are correct. But it seems premature until transit from RecurviseMutex to Mutex happens. Btw, do you see downsides of it?

Copy link
Member

@hebasto hebasto left a 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).

@promag
Copy link
Contributor Author

promag commented Aug 31, 2020

Actually moving implementation class declaration into a header will help.

I don't understand what you mean, please elaborate.

@ryanofsky
Copy link
Contributor

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.

@ryanofsky
Copy link
Contributor

Actually moving implementation class declaration into a header will help.

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.

@hebasto
Copy link
Member

hebasto commented Aug 31, 2020

@ryanofsky

Actually moving implementation class declaration into a header will help.

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 LOCK_RETURNED aka RETURN_CAPABILITY.

@promag

Actually moving implementation class declaration into a header will help.

I don't understand what you mean, please elaborate.

Mind looking into this branch: https://github.com/hebasto/bitcoin/commits/pr19833-0831-demo ?

@promag
Copy link
Contributor Author

promag commented Nov 7, 2020

@hebasto rebased to have a fresh build, mind taking a 2nd look?

@meshcollider ping.

Copy link
Member

@hebasto hebasto left a 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.

@@ -348,6 +348,7 @@ class WalletImpl : public Wallet
}
WalletBalances getBalances() override
{
LOCK(m_wallet->cs_wallet);
Copy link
Member

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?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WITH_LOCK?

Copy link
Member

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.

Copy link
Contributor Author

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.

Copy link
Member

@hebasto hebasto left a 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.

Copy link
Contributor

@ryanofsky ryanofsky left a 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.

@hebasto
Copy link
Member

hebasto commented Sep 3, 2021

@promag

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.
Copy link
Contributor

@ryanofsky ryanofsky left a 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

Copy link
Member

@hebasto hebasto left a 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.

@promag
Copy link
Contributor Author

promag commented Sep 4, 2021

To be fair #22100 simplified this change, 97dbdcd is no longer necessary.

@maflcko maflcko merged commit 9393666 into bitcoin:master Sep 7, 2021
sidhujag pushed a commit to syscoin/syscoin that referenced this pull request Sep 7, 2021
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
@bitcoin bitcoin locked as resolved and limited conversation to collaborators Sep 7, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants