-
Notifications
You must be signed in to change notification settings - Fork 36.3k
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
consensus: Avoid data race in CBlock class #14803
Conversation
@fanquake Done. |
618498c
to
945a642
Compare
Thanks for working on this. Simply making the check flag atomic doesn't really seem correct to me-- why would we be checking the same block object twice concurrently? Just making the test atomic prevents the that particular bit of UB but it doesn't mean that there isn't wasted work, or even the potential of a deadlock. Can someone please summarize how the same block can get checked in parallel and why it makes sense for that to happen? 14058 simply states the test fail with thread sanitizing enabled, but don't explain the sequence of events that lead to the race. I want to make sure that we're not bandaging over a structural flaw that should be fixed with a lock someplace or some other change. |
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. |
I agree with @gmaxwell, why make data structure thread safe? Beside, |
The race happens because we run 10 threads in parallel that check 1000 random blocks in sequence. With only about 100 blocks in total, it is unlikely that every thread picks blocks that have not yet been picked by another thread.
|
I think 2nd option is the most reasonable. |
My preference is avoid adding synchronization primitives to structures that don't need it. Here it seems the case that the validation logic doesn't actually supported multi-threaded block validation, but the unit tests verify (a small) part of it regardless. That seems overkill. |
If it doesn't support multi-threaded block validation, it should still be fixed to avoid multiple threads calling it at the same time, because that is a thing that can happen in practice with the rpc thread running along the "main thread". |
It doesn't support multithreaded validation and there are lot of things that prevent that, which is why I was concerned. Why doesn't the lock on the block index or even cs main prevent concurrency here? I'd missed that the original case was a unit test. |
c5ed6e7 Move CheckBlock() call to critical section (Hennadii Stepanov) Pull request description: This is an alternative to #14803. Refs: - #14058 - #14072 - #14803 (comment) by @gmaxwell > It doesn't support multithreaded validation and there are lot of things that prevent that, which is why I was concerned. Why doesn't the lock on the block index or even cs main prevent concurrency here? - #14803 (comment) by @MarcoFalke Tree-SHA512: 2152e97106e11da5763b2748234ecd2982daadab13a0da04215f4db60af802a44ab5700f32249137d122eb13fc2a02e0f2d561d364607d727d8c6ab879339afb
…ction c5ed6e7 Move CheckBlock() call to critical section (Hennadii Stepanov) Pull request description: This is an alternative to bitcoin#14803. Refs: - bitcoin#14058 - bitcoin#14072 - bitcoin#14803 (comment) by @gmaxwell > It doesn't support multithreaded validation and there are lot of things that prevent that, which is why I was concerned. Why doesn't the lock on the block index or even cs main prevent concurrency here? - bitcoin#14803 (comment) by @MarcoFalke Tree-SHA512: 2152e97106e11da5763b2748234ecd2982daadab13a0da04215f4db60af802a44ab5700f32249137d122eb13fc2a02e0f2d561d364607d727d8c6ab879339afb
…ction c5ed6e7 Move CheckBlock() call to critical section (Hennadii Stepanov) Pull request description: This is an alternative to bitcoin#14803. Refs: - bitcoin#14058 - bitcoin#14072 - bitcoin#14803 (comment) by @gmaxwell > It doesn't support multithreaded validation and there are lot of things that prevent that, which is why I was concerned. Why doesn't the lock on the block index or even cs main prevent concurrency here? - bitcoin#14803 (comment) by @MarcoFalke Tree-SHA512: 2152e97106e11da5763b2748234ecd2982daadab13a0da04215f4db60af802a44ab5700f32249137d122eb13fc2a02e0f2d561d364607d727d8c6ab879339afb
…ction c5ed6e7 Move CheckBlock() call to critical section (Hennadii Stepanov) Pull request description: This is an alternative to bitcoin#14803. Refs: - bitcoin#14058 - bitcoin#14072 - bitcoin#14803 (comment) by @gmaxwell > It doesn't support multithreaded validation and there are lot of things that prevent that, which is why I was concerned. Why doesn't the lock on the block index or even cs main prevent concurrency here? - bitcoin#14803 (comment) by @MarcoFalke Tree-SHA512: 2152e97106e11da5763b2748234ecd2982daadab13a0da04215f4db60af802a44ab5700f32249137d122eb13fc2a02e0f2d561d364607d727d8c6ab879339afb
Ref: #14058, #14072
CheckBlock can be invoked from multiple threads in parallel. To avoid a data race
std::atomic<bool>
is used.All comments from #14072 are addressed.
As this PR introduces copy constructors for both
CBlockHeader
andCBlock
classes, additional refactoring proposed forCBlock::GetBlockHeader()
.