-
Notifications
You must be signed in to change notification settings - Fork 37.7k
refactor: replace isPotentialtip/waitForNotifications by higher method #15842
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
src/wallet/wallet.cpp
Outdated
// for the queue to drain enough to execute it (indicating we are caught up | ||
// at least with the time we entered this function). | ||
chain().waitForNotifications(); | ||
chain().waitForNotificationsUpToTip(m_last_block_processed); |
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.
Accessing m_last_block_processed
requires the cs_wallet
lock. I think to make this work you'll need to:
- grab
cs_wallet
- access
m_last_block_processed
- release
cs_wallet
- call the
waitForNotificationsUpToTip
interface method
Alternatively, we could make m_last_block_processed
an atomic.
Thoughts, @ryanofsky ?
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.
Yes, John's right this needs to synchronize access to m_last_block_processed. Since I don't think there's a straightforward way to make uint256 atomic, maybe a clean way to do this would be to add a new sync.h
macro:
-chain().waitForNotificationsUpToTip(m_last_block_processed);
+chain().waitForNotificationsUpToTip(WITH_LOCK(cs_wallet, return m_last_block_processed));
//! Run code while locking a mutex.
//!
//! Examples:
//!
//! WITH_LOCK(cs, shared_val = shared_val + 1);
//!
//! int val = WITH_LOCK(cs, return shared_val);
//!
#define WITH_LOCK(cs, code) [&]{ LOCK(cs); code; }()
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 like the macro, but I don't like putting the complete expression in the waitForNotificationsUpToTip()
function call. It's too easy for a casual observer to think that the lock is held for the entire call to waitForNotificationsUpToTip()
(which of course would cause a deadlock). How about:
uint256 last_block_hash = WITH_LOCK(cs_wallet, m_last_block_processed);
chain().waitForNotificationsUpToTip(last_block_hash);
which perhaps compiles to the same thing.
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.
Ah yes, wasn't sure of cs_wallet lock covering. Added a WITH_LOCK commit and used to get back m_last_block_processed as showed in example.
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. |
src/interfaces/chain.h
Outdated
//! Wait for pending notifications to be processed unless block hash points to the current, | ||
//! chain tip, or to a possible descendant of the current chain tip that isn't currently | ||
//! connected. | ||
virtual void waitForNotificationsUpToTip(const uint256& hash) = 0; |
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 the "wait up to" name I suggested earlier in the todo comment is misleading, because this isn't really deciding what to wait for based on the argument, but deciding whether to wait based on the argument.
I think a better name might be waitForNotificationsIfNewBlocks(old_tip)
or waitForNotificationsIfNewBlocksConnected(old_tip)
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.
Yes agree wasn't clear so I added Tip
but even followed waitForNotificationsIfNewBlocksConnected(old_tip)
suggestion, a little bit more verbose but far more insightful
src/wallet/wallet.cpp
Outdated
// for the queue to drain enough to execute it (indicating we are caught up | ||
// at least with the time we entered this function). | ||
chain().waitForNotifications(); | ||
chain().waitForNotificationsUpToTip(m_last_block_processed); |
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.
Yes, John's right this needs to synchronize access to m_last_block_processed. Since I don't think there's a straightforward way to make uint256 atomic, maybe a clean way to do this would be to add a new sync.h
macro:
-chain().waitForNotificationsUpToTip(m_last_block_processed);
+chain().waitForNotificationsUpToTip(WITH_LOCK(cs_wallet, return m_last_block_processed));
//! Run code while locking a mutex.
//!
//! Examples:
//!
//! WITH_LOCK(cs, shared_val = shared_val + 1);
//!
//! int val = WITH_LOCK(cs, return shared_val);
//!
#define WITH_LOCK(cs, code) [&]{ LOCK(cs); code; }()
1bcf91d
to
a4c51ed
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.
utACK a4c51ed with a couple of minor nits.
Please remove the @ryanofsky
from the commit log. Github buries you in notifications if your name appears in a commit log. You can keep the ryanofsky
as long as it's not prefixed by @
.
Results from ryanofksy suggestion on isPotentialTip/ waitForNotifications refactoring
9bf61e0
to
deb5f75
Compare
Noted for the github trick, solved the nits on deb5f75 |
Doesn't build. Please build/test locally before pushing 🙂 |
deb5f75
to
57007b8
Compare
Sorry for that, working on dev scripts to avoid this kind of mistake even for nits updates! |
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.
utACK 57007b8. This change isn't as much of a simplification as I was hoping when I wrote the TODO suggesting it, but it's good to remove this one Chain::Lock usage, just as a prerequisite for removing the entire Chain::Lock interface later.
One more suggestion would be to add GUARDED_BY(cs_wallet)
annotation to:
Line 690 in cd14d21
uint256 m_last_block_processed; |
because after this PR, accesses are now guarded by cs_wallet
instead of cs_main
.
Add GUARDED_BY(cs_wallet) annotation to m_last_block_processed, given that its now guarded by cs_wallet instead of cs_main
57007b8
to
4226779
Compare
Updated at 4226779 with GUARDED_BY annotation addition. (btw @ryanofsky, I've started to work on removing bits of Chain::Lock interface, notably the GetDepthInMainChain by tracking last_block_processed_height in CWallet, hope to PR soon to get feedback) |
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.
utACK 4226779. Only change is adding the cs_wallet lock annotation.
I'm glad to hear you're working on removing cs_main locking from GetDepthInMainChain. This should improve performance and allow removing locked_chain variables from a swath of wallet code. I think it'll require adding something like a map from block hash to height for CMerkleTx::hashBlock
blocks, but there could be other approaches.
Maybe hold on a bit on this. While working on removing cs_main locking, it appears to me than, given wallet will be tracking chain height thanks to asynchronous updates and not direct chain state queries, it's needed to And yes doing remove by adding m_last_block_processed_height in both |
I don't think I understand the need to call |
Ah get your point, I'm going to far in locking removing (at least for now), was trying to not rely at all on Chain locking, even without '''::chainActive.Tip()->GetBlockHash()''' call, but only on callbacks hinting chain state. |
ACK 4226779 |
…tions by higher method 4226779 refactor: replace isPotentialtip/waitForNotifications by higher method (Antoine Riard) edfe943 Add WITH_LOCK macro: run code while locking a mutex (Antoine Riard) Pull request description: In Chain interface, instead of a isPotentialTip and a WaitForNotifications method, both used only once in CWallet::BlockUntilSyncedToCurrentChain, combine them in a higher WaitForNotificationsUpToTip method. Semantic should be unchanged, wallet wait for pending notifications to be processed unless block hash points to the current chain tip or a descendant. ACKs for commit 422677: jnewbery: ACK 4226779 ryanofsky: utACK 4226779. Only change is adding the cs_wallet lock annotation. Tree-SHA512: 2834ff0218795ef607543fae822e5cce25d759c1a9cfcb1f896a4af03071faed5276fbe0966e0c6ed65dc0e88af161899c5b2ca358a2d24fe70969a550000bf2
…s by higher method Summary: Add GUARDED_BY(cs_wallet) annotation to m_last_block_processed, given that its now guarded by cs_wallet instead of cs_main bitcoin/bitcoin@4226779 --- Add WITH_LOCK macro: run code while locking a mutex Results from ryanofksy suggestion on isPotentialTip/ waitForNotifications refactoring bitcoin/bitcoin@edfe943 --- Depends on D6258 Backport of Core [[bitcoin/bitcoin#15842 | PR15842]] Test Plan: ninja check-all Reviewers: #bitcoin_abc, deadalnix Reviewed By: #bitcoin_abc, deadalnix Differential Revision: https://reviews.bitcoinabc.org/D6260
partial bitcoin#15842, merge bitcoin#15849, bitcoin#17342, bitcoin#18710: Add local thread pool to CCheckQueue
In Chain interface, instead of a isPotentialTip and a WaitForNotifications method, both used only once in CWallet::BlockUntilSyncedToCurrentChain, combine them in a higher WaitForNotificationsUpToTip method. Semantic should be unchanged, wallet wait for pending notifications to be processed unless block hash points to the current chain tip or a descendant.