mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-06-03 17:54:19 +02:00
Merge #19668: Do not hide compile-time thread safety warnings
ea74e10acfdoc: Add best practice for annotating/asserting locks (Hennadii Stepanov)2ee7743fe7sync.h: Make runtime lock checks require compile-time lock checks (Anthony Towns)23d71d171eDo not hide compile-time thread safety warnings (Hennadii Stepanov)3ddc150857Add missed thread safety annotations (Hennadii Stepanov)af9ea55a72Use LockAssertion utility class instead of AssertLockHeld() (Hennadii Stepanov) Pull request description: On the way of transit from `RecursiveMutex` to `Mutex` (see #19303) it is crucial to have run-time `AssertLockHeld()` assertion that does _not_ hide compile-time Clang Thread Safety Analysis warnings. On master (65e4ecabd5) using `AssertLockHeld()` could hide Clang Thread Safety Analysis warnings, e.g., with the following patch applied: ```diff --- a/src/txmempool.h +++ b/src/txmempool.h @@ -607,7 +607,7 @@ public: void addUnchecked(const CTxMemPoolEntry& entry, setEntries& setAncestors, bool validFeeEstimate = true) EXCLUSIVE_LOCKS_REQUIRED(cs, cs_main); void removeRecursive(const CTransaction& tx, MemPoolRemovalReason reason) EXCLUSIVE_LOCKS_REQUIRED(cs); - void removeForReorg(const CCoinsViewCache* pcoins, unsigned int nMemPoolHeight, int flags) EXCLUSIVE_LOCKS_REQUIRED(cs, cs_main); + void removeForReorg(const CCoinsViewCache* pcoins, unsigned int nMemPoolHeight, int flags) EXCLUSIVE_LOCKS_REQUIRED(cs_main); void removeConflicts(const CTransaction& tx) EXCLUSIVE_LOCKS_REQUIRED(cs); void removeForBlock(const std::vector<CTransactionRef>& vtx, unsigned int nBlockHeight) EXCLUSIVE_LOCKS_REQUIRED(cs); ``` Clang compiles the code without any thread safety warnings. See "Add missed thread safety annotations" commit for the actual thread safety warnings that are fixed in this PR. ACKs for top commit: MarcoFalke: ACKea74e10acf🎙 jnewbery: ACKea74e10acfajtowns: ACKea74e10acfTree-SHA512: 8cba996e526751a1cb0e613c0cc1b10f027a3e9945fbfb4bd30f6355fd36b9f9c2e1e95ed3183fc254b42df7c30223278e18e5bdb5e1ef85db7fef067595d447
This commit is contained in:
@@ -746,6 +746,72 @@ the upper cycle, etc.
|
||||
Threads and synchronization
|
||||
----------------------------
|
||||
|
||||
- Prefer `Mutex` type to `RecursiveMutex` one
|
||||
|
||||
- Consistently use [Clang Thread Safety Analysis](https://clang.llvm.org/docs/ThreadSafetyAnalysis.html) annotations to
|
||||
get compile-time warnings about potential race conditions in code. Combine annotations in function declarations with
|
||||
run-time asserts in function definitions:
|
||||
|
||||
```C++
|
||||
// txmempool.h
|
||||
class CTxMemPool
|
||||
{
|
||||
public:
|
||||
...
|
||||
mutable RecursiveMutex cs;
|
||||
...
|
||||
void UpdateTransactionsFromBlock(...) EXCLUSIVE_LOCKS_REQUIRED(::cs_main, cs);
|
||||
...
|
||||
}
|
||||
|
||||
// txmempool.cpp
|
||||
void CTxMemPool::UpdateTransactionsFromBlock(...)
|
||||
{
|
||||
AssertLockHeld(::cs_main);
|
||||
AssertLockHeld(cs);
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
```C++
|
||||
// validation.h
|
||||
class ChainstateManager
|
||||
{
|
||||
public:
|
||||
...
|
||||
bool ProcessNewBlock(...) EXCLUSIVE_LOCKS_REQUIRED(!::cs_main);
|
||||
...
|
||||
}
|
||||
|
||||
// validation.cpp
|
||||
bool ChainstateManager::ProcessNewBlock(...)
|
||||
{
|
||||
AssertLockNotHeld(::cs_main);
|
||||
...
|
||||
LOCK(::cs_main);
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
- When Clang Thread Safety Analysis is unable to determine if a mutex is locked, use `LockAssertion` class instances:
|
||||
|
||||
```C++
|
||||
// net_processing.h
|
||||
void RelayTransaction(...) EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
|
||||
|
||||
// net_processing.cpp
|
||||
void RelayTransaction(...)
|
||||
{
|
||||
AssertLockHeld(::cs_main);
|
||||
|
||||
connman.ForEachNode([&txid, &wtxid](CNode* pnode) {
|
||||
LockAssertion lock(::cs_main);
|
||||
...
|
||||
});
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
- Build and run tests with `-DDEBUG_LOCKORDER` to verify that no potential
|
||||
deadlocks are introduced. As of 0.12, this is defined by default when
|
||||
configuring with `--enable-debug`.
|
||||
|
||||
Reference in New Issue
Block a user