sync: Use StdMutex for thread safety annotations
What changed, and why it matters
This is a small internal cleanup in Bitcoin Core's lock-tracking code. It swaps the standard C++ mutex for a project-specific wrapper (StdMutex) and adds compile-time annotations that tell the compiler which data structures are protected by the mutex. There is no change to network behavior, consensus rules, or user-facing functionality, and no security bug is being fixed.
No action required; treat as routine maintenance/refactoring.
Security signals we found
No security-relevant behavioral change
Refactoring to use project mutex abstractions
Addition of thread-safety compile-time annotations
Evidence from the diff
The commit modifies src/sync.cpp to use StdMutex and STDLOCK in place of std::mutex/std::lock_guard for the deadlock-detection mutex (dd_mutex). It also adds GUARDED_BY(dd_mutex) annotations to LockData members. This is a refactoring change intended to make thread-safety analysis consistent with the rest of the codebase; it does not alter locking semantics or fix a vulnerability.
Changed components
src/sync.cpp deadlock-detection internalsInspect captured patch +12 / −11
diff --git a/src/sync.cpp b/src/sync.cpp
index 0e5c623d..6d740866 100644
--- a/src/sync.cpp
+++ b/src/sync.cpp
@@ -7,6 +7,7 @@
#include <logging/timer.h>
#include <tinyformat.h>
#include <util/log.h>
+#include <util/stdmutex.h>
#include <util/strencodings.h>
#include <util/threadnames.h>
@@ -87,10 +88,10 @@ using LockOrders = std::map<LockPair, LockStack>;
using InvLockOrders = std::set<LockPair>;
struct LockData {
- LockStacks m_lock_stacks;
- LockOrders lockorders;
- InvLockOrders invlockorders;
- std::mutex dd_mutex;
+ LockStacks m_lock_stacks GUARDED_BY(dd_mutex);
+ LockOrders lockorders GUARDED_BY(dd_mutex);
+ InvLockOrders invlockorders GUARDED_BY(dd_mutex);
+ StdMutex dd_mutex;
};
LockData& GetLockData() {
@@ -166,7 +167,7 @@ static void push_lock(MutexType* c, const CLockLocation& locklocation)
std::is_base_of_v<std::recursive_mutex, MutexType>;
LockData& lockdata = GetLockData();
- std::lock_guard<std::mutex> lock(lockdata.dd_mutex);
+ STDLOCK(lockdata.dd_mutex);
LockStack& lock_stack = lockdata.m_lock_stacks[std::this_thread::get_id()];
lock_stack.emplace_back(c, locklocation);
@@ -206,7 +207,7 @@ static void push_lock(MutexType* c, const CLockLocation& locklocation)
static void pop_lock()
{
LockData& lockdata = GetLockData();
- std::lock_guard<std::mutex> lock(lockdata.dd_mutex);
+ STDLOCK(lockdata.dd_mutex);
LockStack& lock_stack = lockdata.m_lock_stacks[std::this_thread::get_id()];
lock_stack.pop_back();
@@ -226,7 +227,7 @@ template void EnterCritical(const char*, const char*, int, std::recursive_mutex*
void CheckLastCritical(void* cs, std::string& lockname, const char* guardname, const char* file, int line)
{
LockData& lockdata = GetLockData();
- std::lock_guard<std::mutex> lock(lockdata.dd_mutex);
+ STDLOCK(lockdata.dd_mutex);
const LockStack& lock_stack = lockdata.m_lock_stacks[std::this_thread::get_id()];
if (!lock_stack.empty()) {
@@ -257,7 +258,7 @@ void LeaveCritical()
static std::string LocksHeld()
{
LockData& lockdata = GetLockData();
- std::lock_guard<std::mutex> lock(lockdata.dd_mutex);
+ STDLOCK(lockdata.dd_mutex);
const LockStack& lock_stack = lockdata.m_lock_stacks[std::this_thread::get_id()];
std::string result;
@@ -269,7 +270,7 @@ static std::string LocksHeld()
static bool LockHeld(void* mutex)
{
LockData& lockdata = GetLockData();
- std::lock_guard<std::mutex> lock(lockdata.dd_mutex);
+ STDLOCK(lockdata.dd_mutex);
const LockStack& lock_stack = lockdata.m_lock_stacks[std::this_thread::get_id()];
for (const LockStackItem& i : lock_stack) {
@@ -302,7 +303,7 @@ template void AssertLockNotHeldInternal(const char*, const char*, int, Recursive
void DeleteLock(void* cs)
{
LockData& lockdata = GetLockData();
- std::lock_guard<std::mutex> lock(lockdata.dd_mutex);
+ STDLOCK(lockdata.dd_mutex);
const LockPair item = std::make_pair(cs, nullptr);
LockOrders::iterator it = lockdata.lockorders.lower_bound(item);
while (it != lockdata.lockorders.end() && it->first.first == cs) {
@@ -321,7 +322,7 @@ void DeleteLock(void* cs)
bool LockStackEmpty()
{
LockData& lockdata = GetLockData();
- std::lock_guard<std::mutex> lock(lockdata.dd_mutex);
+ STDLOCK(lockdata.dd_mutex);
const auto it = lockdata.m_lock_stacks.find(std::this_thread::get_id());
if (it == lockdata.m_lock_stacks.end()) {
return true;
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.