-
Notifications
You must be signed in to change notification settings - Fork 37.7k
validation: Guard chainman chainstates with cs_main #21025
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
validation: Guard chainman chainstates with cs_main #21025
Conversation
c1d4af7
to
5b8118e
Compare
5b8118e
to
f92dc65
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 f92dc65
I've left a few style comments, but this seems fine.
f92dc65
to
e6eb8d2
Compare
Code review ACK e6eb8d2 |
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. ConflictsNo conflicts as of last run. |
cr ACK e6eb8d2: patch looks correct |
Any reason to only add the annotation to (1/3) of the |
The older version was merged as part of #20749. Perhaps we should repurpose this PR to address the review comments (particularly #21025 (comment))? |
3f24a72
to
24fcc4c
Compare
As suggested by @jnewbery, this PR has been repurposed to address #21025 (comment) |
Since these chainstates are: 1. Also vulnerable to the race condition described in the previous commit 2. Documented as having similar semantics as m_active_chainstate we should also protect them with ::cs_main.
24fcc4c
to
20677ff
Compare
|
code review ACK 20677ff. I've verified by eye that neither of these members are accessed without cs_main. In the commit message, "Also vulnerable to the race condition described in the previous commit" no longer makes sense since f92dc65 is not the previous commit. A couple of potential follow-ups:
|
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 20677ff. It is safer to have these new GUARDED_BY
annotations and locks than not to have them, but in the longer run I think every LOCK(cs_main)
added here and added earlier in f92dc65 from #20749 should be removed and replaced with EXCLUSIVE_LOCKS_REQUIRED(cs_main)
on the accessor methods instead. cs_main
is a high level lock that should be explicitly acquired at a high level to prevent the chain state from changing. It shouldn't be acquired recursively in low-level methods just to read pointer values atomically.
After #19806 and its followups, the active chainstate pointer will be able to change at runtime, and code calling these accessor methods should care if the results they return are still up-to-date after returning. That code should be explicitly locking cs_main
and making sure state is locked the right amount of time, not relying on recursive locking and potentially using outdated or inconsistent state pointers.
IIUC changing this now would make #19806 more difficult to rebase so is reasonable to delay. But after #19806 is done with, it would be good for all the new locks added in f92dc65 and
20677ff to be removed and replaced with lock required annotations, and for calling code like ProcessNewBlock
to either lock or save pointers correctly and not rely on ActiveChainstate()
and related methods return values to not change.
20677ff validation: Guard all chainstates with cs_main (Carl Dong) Pull request description: ``` This avoids a potential race-condition where a thread is reading the ChainstateManager::m_active_chainstate pointer while another one is writing to it. There is no portable guarantee that reading/writing the pointer is thread-safe. This is also done in way that mimics ::ChainstateActive(), so the transition from that function to this method is easy. More discussion: 1. bitcoin#20749 (comment) 2. bitcoin#19806 (comment) 3. bitcoin#19806 (comment) 4. bitcoin#19806 (comment) ``` Basically this PR removes the loaded-but-unfired footgun, which: - Is multiplied (but still unshot) in the chainman deglobalization PRs (bitcoin#20158) - Is shot in the test framework in the au.activate PR (bitcoin#19806) ACKs for top commit: jnewbery: code review ACK 20677ff. I've verified by eye that neither of these members are accessed without cs_main. ryanofsky: Code review ACK 20677ff. It is safer to have these new `GUARDED_BY` annotations and locks than not to have them, but in the longer run I think every `LOCK(cs_main)` added here and added earlier in f92dc65 from bitcoin#20749 should be removed and replaced with `EXCLUSIVE_LOCKS_REQUIRED(cs_main)` on the accessor methods instead. `cs_main` is a high level lock that should be explicitly acquired at a high level to prevent the chain state from changing. It shouldn't be acquired recursively in low-level methods just to read pointer values atomically. Tree-SHA512: 68a3a46d79a407b774eab77e1d682a97e95f1672db0a5fcb877572e188bec09f3a7b47c5d0cc1f2769ea276896dcbe97cb35c861acf7d8e3e513e955dc773f89
Summary: PR description: > This avoids a potential race-condition where a thread is reading the > ChainstateManager::m_active_chainstate pointer while another one is > writing to it. There is no portable guarantee that reading/writing the > pointer is thread-safe. This is a backport of [[bitcoin/bitcoin#21025 | core#21025]] Test Plan: With debug and tsan: `ninja check check-functional` Reviewers: #bitcoin_abc, Fabien Reviewed By: #bitcoin_abc, Fabien Differential Revision: https://reviews.bitcoinabc.org/D11773
Basically this PR removes the loaded-but-unfired footgun, which: