validation, refactor: add missing thread safety lock assertions #24177
pull jonatack wants to merge 2 commits into bitcoin:master from jonatack:add-missing-lock-assertions-in-validation changing 2 files +54 −11-
jonatack commented at 11:56 am on January 27, 2022: memberA number of functions in validation.{h,cpp} have a thread safety lock annotation in the declaration but are missing the corresponding run-time lock assertion in the definition.
-
jonatack commented at 12:05 pm on January 27, 2022: member
How to review: verify that a Clang debug build is clean (no
-Wthread-safety-analysis
warnings) and that each lock assertion (AssertLockHeld
) has a corresponding lock annotation (EXCLUSIVE_LOCKS_REQUIRED
) in the declaration.For more information about Clang thread safety analysis, see - https://clang.llvm.org/docs/ThreadSafetyAnalysis.html - https://github.com/bitcoin/bitcoin/blob/master/doc/developer-notes.md#lockingmutex-usage-notes - https://github.com/bitcoin/bitcoin/blob/master/doc/developer-notes.md#threads-and-synchronization
-
DrahtBot added the label Validation on Jan 27, 2022
-
in src/validation.cpp:2660 in fe73d8fad1 outdated
2657@@ -2650,6 +2658,7 @@ bool CChainState::ConnectTip(BlockValidationState& state, CBlockIndex* pindexNew 2658 * known to be invalid (it's however far from certain to be valid). 2659 */ 2660 CBlockIndex* CChainState::FindMostWorkChain() {
shaavan commented at 2:29 pm on January 27, 2022:nit:
0CBlockIndex* CChainState::FindMostWorkChain() 1{
jonatack commented at 2:52 pm on January 27, 2022:donein src/validation.cpp:1530 in fe73d8fad1 outdated
1525@@ -1524,6 +1526,8 @@ void CChainState::CheckForkWarningConditions() 1526 // Called both upon regular invalid block discovery *and* InvalidateBlock 1527 void CChainState::InvalidChainFound(CBlockIndex* pindexNew) 1528 { 1529+ AssertLockHeld(cs_main); 1530+
shaavan commented at 2:30 pm on January 27, 2022:nit:
jonatack commented at 2:52 pm on January 27, 2022:donein src/validation.cpp:5035 in fe73d8fad1 outdated
5030@@ -5014,6 +5031,8 @@ void ChainstateManager::Reset() 5031 5032 void ChainstateManager::MaybeRebalanceCaches() 5033 { 5034+ AssertLockHeld(::cs_main); 5035+
shaavan commented at 2:35 pm on January 27, 2022:nit:
jonatack commented at 2:52 pm on January 27, 2022:donein src/validation.h:531 in fe73d8fad1 outdated
528@@ -529,6 +529,7 @@ class CChainState 529 //! @returns whether or not the CoinsViews object has been fully initialized and we can 530 //! safely flush this object to disk. 531 bool CanFlushToDisk() const EXCLUSIVE_LOCKS_REQUIRED(cs_main) {
shaavan commented at 2:35 pm on January 27, 2022:nit:
0 bool CanFlushToDisk() const EXCLUSIVE_LOCKS_REQUIRED(cs_main) 1 {
jonatack commented at 2:52 pm on January 27, 2022:doneshaavan commented at 2:36 pm on January 27, 2022: contributorConcept ACK
I think it makes sense to add the missing thread-safety lock assertions, which prevents the risk of a race condition.
I shall take a thorough look at this PR before ACKing it. Meanwhile, I found some nit suggestions that should be addressed.
jonatack force-pushed on Jan 27, 2022hebasto commented at 9:29 pm on January 28, 2022: memberConcept ACK, it follows https://github.com/bitcoin/bitcoin/blob/master/doc/developer-notes.md#threads-and-synchronization.shaavan commented at 12:23 pm on January 30, 2022: contributorI looked into both
src/validation.cpp
andsrc/validation.h
, and I found a list of functions that are declared usingEXCLUSIVE_LOCK_REQUIRED()
but does not haveAssertLockHeld()
in their definition, and are also not yet addressed in this PR.Declared in src/validation.cpp:
- LimitMempoolSize
[EXCLUSIVE_LOCKS_REQUIRED(pool.cs, ::cs_main)]
- CheckFeeRate
[EXCLUSIVE_LOCKS_REQUIRED(cs_main, m_pool.cs)]
- AcceptToMemoryPool
[EXCLUSIVE_LOCKS_REQUIRED(cs_main)]
- ContextualCheckBlockHeader
[EXCLUSIVE_LOCKS_REQUIRED(cs_main)]
- PreChecks
[EXCLUSIVE_LOCKS_REQUIRED(cs_main, m_pool.cs)]
- PolicyScriptChecks
[EXCLUSIVE_LOCKS_REQUIRED(cs_main, m_pool.cs)]
- ConsensusScriptChecks
[EXCLUSIVE_LOCKS_REQUIRED(cs_main, m_pool.cs)]
- Finalize
[EXCLUSIVE_LOCKS_REQUIRED(cs_main, m_pool.cs)]
Declared in src/validation.h:
DisconnectTip[EXCLUSIVE_LOCKS_REQUIRED(cs_main, m_mempool->cs)]
but onlyAssertLockHeld(cs_main)
- ProcessTransaction
[EXCLUSIVE_LOCKS_REQUIRED(cs_main)]
I think all of these functions come in the scope of this PR, and should be addressed in it.
Edit: DisconnectTip() has
AssertLockHeld()
statement for both the mutex. So no need to make any changes to it. Thanks @jonatack for catching it.Done, except for touching the
DisconnectTip()
conditional lock assertion onm_mempool->cs
jonatack force-pushed on Jan 30, 2022shaavan approvedshaavan commented at 10:16 am on January 31, 2022: contributorBtw I was curious about one thing. Why some functions haveAssertLockHeld(cs_main)
and someAssertLockHeld(::cs_main)
?jonatack commented at 10:19 am on January 31, 2022: memberBtw I was curious about one thing. Why some functions have
AssertLockHeld(cs_main)
and someAssertLockHeld(::cs_main)
?Good question. See #22932 (review)
MarcoFalke added the label Refactoring on Jan 31, 2022shaavan commented at 11:04 am on January 31, 2022: contributorSo what I understood from #22932 (comment) is that::cs_main
is preferred overcs_main
because the former one explicitly indicates that it’s a global mutex. And each time a function is updated,cs_main
should be converted to::cs_main
if not already done. If my analysis is erroneous, please do correct me. And thanks, @jonatack, for helping with clarification.shaavan commented at 11:09 am on January 31, 2022: contributorI found a minor nit that I didn’t address in my previous review. Feel free to ignore, in case not updating the PR for another reason.in src/validation.cpp:293 in 1c0737e9cc outdated
287@@ -288,6 +288,9 @@ static unsigned int GetBlockScriptFlags(const CBlockIndex* pindex, const Consens 288 static void LimitMempoolSize(CTxMemPool& pool, CCoinsViewCache& coins_cache, size_t limit, std::chrono::seconds age) 289 EXCLUSIVE_LOCKS_REQUIRED(pool.cs, ::cs_main) 290 { 291+ AssertLockHeld(pool.cs); 292+ AssertLockHeld(::cs_main); 293+
shaavan commented at 11:10 am on January 31, 2022:nit:
jonatack commented at 1:02 pm on January 31, 2022:Ok. Will do if need to retouch.
jonatack commented at 7:35 pm on February 8, 2022:Donejonatack commented at 1:05 pm on January 31, 2022: membereach time a function is updated,
cs_main
should be converted to::cs_main
if not already doneFor new code, yes; for updated code, I suppose it depends on the PR author and on reviewer feedback.
(Thanks for reviewing here!)
DrahtBot commented at 5:43 am on February 2, 2022: memberThe following sections might be updated with supplementary metadata relevant to reviewers and maintainers.
Conflicts
Reviewers, this pull request conflicts with the following ones:
- #24232 (assumeutxo: add init and completion logic by jamesob)
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.
jonatack force-pushed on Feb 8, 2022jonatack force-pushed on Feb 8, 2022vasild approvedvasild commented at 12:06 pm on February 9, 2022: memberACK 686d35de6bd769efba35177cd9c91f431f46e5a5
ChainstateManager::Reset()
is called just from the destructorChainstateManager::~ChainstateManager()
and from a test, but from the test the destructor is called shortly after. So, maybe theReset()
method can be removed, its body copied to the destructor and the explicit call toReset()
from the test removed? The only difference is that now, from the test,Reset()
is called first andUnloadBlockIndex()
is called afterwards (via the destructor). That order will be swapped, a cursory look shows that should be ok.jonatack commented at 1:46 pm on February 9, 2022: memberThanks @vasild for having a look.
maybe the
Reset()
method can be removed, its body copied to the destructor and the explicit call toReset()
from the test removedDone. It looks like
Reset()
was added in 89cdf4d5692 when the requirements probably weren’t finalized. Also saw that we can replace thecs_main
lock inUnloadBlockIndex()
with a thread safety annotation. Updated pergit diff 686d35d 9a18bdb
.jonatack force-pushed on Feb 9, 2022MarcoFalke commented at 1:55 pm on February 9, 2022: memberMind splitting the inline refactor from the annotations refactor into another pull? If not, that is fine, too.jonatack force-pushed on Feb 9, 2022in src/validation.cpp:291 in acdead8a26 outdated
287@@ -288,6 +288,8 @@ static unsigned int GetBlockScriptFlags(const CBlockIndex* pindex, const Consens 288 static void LimitMempoolSize(CTxMemPool& pool, CCoinsViewCache& coins_cache, size_t limit, std::chrono::seconds age) 289 EXCLUSIVE_LOCKS_REQUIRED(pool.cs, ::cs_main) 290 { 291+ AssertLockHeld(pool.cs); 292+ AssertLockHeld(::cs_main);
hebasto commented at 5:21 pm on February 9, 2022:nit: Reorder here and inEXCLUSIVE_LOCKS_REQUIRED
?
jonatack commented at 6:24 pm on February 9, 2022:Done (thanks!)hebasto approvedhebasto commented at 5:22 pm on February 9, 2022: memberACK acdead8a26e92991987efb346566b5474aff8e74, I have reviewed the code (it was a bit tedious :smile:) and it looks OK, I agree it can be merged.Add missing thread safety lock assertions in validation.cpp
Co-authored-by: Shashwat <svangani239@gmail.com>
Add missing thread safety lock assertions in validation.h f485a07454jonatack force-pushed on Feb 9, 2022hebasto approvedvasild approvedvasild commented at 2:36 pm on February 16, 2022: memberACK f485a0745455b46390f1c14260643ad69c8fe2adMarcoFalke merged this on Feb 17, 2022MarcoFalke closed this on Feb 17, 2022
jonatack deleted the branch on Feb 17, 2022laanwj referenced this in commit cba41db327 on Mar 7, 2022Fabcien referenced this in commit 7c8d98584d on Dec 19, 2022DrahtBot locked this on Feb 17, 2023
github-metadata-mirror
This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2024-12-22 06:12 UTC
This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me