Skip to content

Commit 952546d

Browse files
committed
Address gaps in concurrency thread safety
1 parent 39c3ec5 commit 952546d

19 files changed

Lines changed: 180 additions & 78 deletions

src/bucket/BucketManager.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ class BucketManager : NonMovableOrCopyable
101101
// mLedgerStateMutex to prevent deadlocks. Code must NOT hold mBucketMutex
102102
// while trying to acquire LedgerManagerImpl::mLedgerStateMutex, as this
103103
// will cause a deadlock.
104-
mutable RecursiveMutex mBucketMutex;
104+
mutable ANNOTATED_RECURSIVE_MUTEX(mBucketMutex);
105105

106106
#ifdef THREAD_SAFETY
107107
private:

src/bucket/BucketSnapshotManager.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ class BucketSnapshotManager : NonMovableOrCopyable
3737
AppConnector& mAppConnector;
3838

3939
// Lock must be held when accessing any member variables holding snapshots
40-
mutable SharedMutex mSnapshotMutex;
40+
mutable ANNOTATED_SHARED_MUTEX(mSnapshotMutex);
4141

4242
// Snapshot that is maintained and periodically updated by BucketManager on
4343
// the main thread. When background threads need to generate or refresh a

src/bucket/LiveBucketIndex.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ LiveBucketIndex::maybeInitializeCache(size_t totalBucketListAccountsSizeBytes,
102102
}
103103

104104
// Cache is already initialized
105-
if (std::shared_lock<std::shared_mutex> lock(mCacheMutex); mCache)
105+
if (SharedLockShared lock(mCacheMutex); mCache)
106106
{
107107
return;
108108
}
@@ -123,7 +123,7 @@ LiveBucketIndex::maybeInitializeCache(size_t totalBucketListAccountsSizeBytes,
123123
return;
124124
}
125125

126-
std::unique_lock<std::shared_mutex> lock(mCacheMutex);
126+
SharedLockExclusive lock(mCacheMutex);
127127
if (totalBucketListAccountsSizeBytes < maxBucketListBytesToCache)
128128
{
129129
// We can cache the entire bucket
@@ -202,7 +202,7 @@ LiveBucketIndex::getCachedEntry(LedgerKey const& k) const
202202
{
203203
if (shouldUseCache() && isCachedType(k))
204204
{
205-
std::shared_lock<std::shared_mutex> lock(mCacheMutex);
205+
SharedLockShared lock(mCacheMutex);
206206
auto cachePtr = mCache->maybeGet(k);
207207
if (cachePtr)
208208
{
@@ -323,7 +323,7 @@ LiveBucketIndex::shouldUseCache() const
323323
{
324324
if (mDiskIndex)
325325
{
326-
std::shared_lock<std::shared_mutex> lock(mCacheMutex);
326+
SharedLockShared lock(mCacheMutex);
327327
return mCache != nullptr;
328328
}
329329

@@ -353,7 +353,7 @@ LiveBucketIndex::maybeAddToCache(
353353
// earlier.
354354
mCacheMissMeter.Mark();
355355

356-
std::unique_lock<std::shared_mutex> lock(mCacheMutex);
356+
SharedLockExclusive lock(mCacheMutex);
357357
mCache->put(k, entry);
358358
}
359359
}
@@ -392,7 +392,7 @@ LiveBucketIndex::getMaxCacheSize() const
392392
{
393393
if (shouldUseCache())
394394
{
395-
std::shared_lock<std::shared_mutex> lock(mCacheMutex);
395+
SharedLockShared lock(mCacheMutex);
396396
return mCache->maxSize();
397397
}
398398

@@ -405,7 +405,7 @@ LiveBucketIndex::getCurrentCacheSize() const
405405
{
406406
if (shouldUseCache())
407407
{
408-
std::shared_lock<std::shared_mutex> lock(mCacheMutex);
408+
SharedLockShared lock(mCacheMutex);
409409
return mCache->size();
410410
}
411411

src/bucket/LiveBucketIndex.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,13 @@
1212
#include "ledger/LedgerHashUtils.h" // IWYU pragma: keep
1313
#include "util/NonCopyable.h"
1414
#include "util/RandomEvictionCache.h"
15+
#include "util/ThreadAnnotations.h"
1516
#include "util/XDROperators.h" // IWYU pragma: keep
1617
#include "xdr/Stellar-ledger-entries.h"
1718
#include <filesystem>
1819
#include <optional>
1920

2021
#include <cereal/archives/binary.hpp>
21-
#include <shared_mutex>
2222

2323
namespace asio
2424
{
@@ -65,8 +65,8 @@ class LiveBucketIndex : public NonMovableOrCopyable
6565
// The indexes themselves are thread safe, as they are immutable after
6666
// construction. The cache is not, all accesses must first acquire this
6767
// mutex.
68-
mutable std::unique_ptr<CacheT> mCache{};
69-
mutable std::shared_mutex mCacheMutex;
68+
mutable std::unique_ptr<CacheT> mCache GUARDED_BY(mCacheMutex){};
69+
mutable ANNOTATED_SHARED_MUTEX(mCacheMutex);
7070

7171
medida::Meter& mCacheHitMeter;
7272
medida::Meter& mCacheMissMeter;

src/invariant/InvariantManagerImpl.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ class InvariantManagerImpl : public InvariantManager
3737
std::string lastFailedWithMessage;
3838
};
3939

40-
Mutex mutable mFailureInformationMutex;
40+
ANNOTATED_MUTEX(mFailureInformationMutex);
4141
std::map<std::string, InvariantFailureInformation>
4242
mFailureInformation GUARDED_BY(mFailureInformationMutex);
4343

src/ledger/LedgerManagerImpl.h

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -296,11 +296,8 @@ class LedgerManagerImpl : public LedgerManager
296296
VirtualClock::time_point mLastClose;
297297

298298
// Use mutex to guard ledger state during apply
299-
mutable RecursiveMutex mLedgerStateMutex
300-
#ifdef THREAD_SAFETY
301-
ACQUIRED_BEFORE(BucketManager::mBucketMutex)
302-
#endif
303-
;
299+
ANNOTATED_RECURSIVE_MUTEX(mLedgerStateMutex,
300+
ACQUIRED_BEFORE(BucketManager::mBucketMutex));
304301

305302
medida::Timer& mCatchupDuration;
306303

@@ -564,6 +561,7 @@ class LedgerManagerImpl : public LedgerManager
564561
virtual bool
565562
isApplying() const override
566563
{
564+
releaseAssert(threadIsMain());
567565
return mCurrentlyApplyingLedger;
568566
}
569567
void markApplyStateReset() override;

src/overlay/FlowControl.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ class FlowControl
6767
size_t mTxQueueByteCount GUARDED_BY(mFlowControlMutex){0};
6868

6969
// Mutex to synchronize flow control state
70-
Mutex mutable mFlowControlMutex;
70+
mutable ANNOTATED_MUTEX(mFlowControlMutex);
7171
// Is this peer currently throttled due to lack of capacity
7272
std::optional<VirtualClock::time_point>
7373
mLastThrottle GUARDED_BY(mFlowControlMutex);

src/overlay/Hmac.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ Hmac::setAuthenticatedMessageBody(AuthenticatedMessage& aMsg,
8383
void
8484
Hmac::damageRecvMacKey()
8585
{
86+
LOCK_GUARD(mMutex, guard);
8687
auto bytes = randomBytes(mRecvMacKey.key.size());
8788
std::copy(bytes.begin(), bytes.end(), mRecvMacKey.key.begin());
8889
}

src/overlay/Hmac.h

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,23 @@
1111

1212
using namespace stellar;
1313

14+
namespace stellar
15+
{
16+
class Peer;
17+
}
18+
1419
class Hmac
1520
{
16-
#ifndef USE_TRACY
17-
Mutex mMutex;
18-
#else
19-
TracyLockable(std::mutex, mMutex);
21+
#ifdef THREAD_SAFETY
22+
// Make the peer class a friend for thread safety analysis
23+
friend class stellar::Peer;
2024
#endif
21-
HmacSha256Key mSendMacKey;
22-
HmacSha256Key mRecvMacKey;
23-
uint64_t mSendMacSeq{0};
24-
uint64_t mRecvMacSeq{0};
25+
26+
ANNOTATED_MUTEX(mMutex);
27+
HmacSha256Key mSendMacKey GUARDED_BY(mMutex);
28+
HmacSha256Key mRecvMacKey GUARDED_BY(mMutex);
29+
uint64_t mSendMacSeq GUARDED_BY(mMutex){0};
30+
uint64_t mRecvMacSeq GUARDED_BY(mMutex){0};
2531

2632
public:
2733
bool setSendMackey(HmacSha256Key const& key);

src/overlay/Peer.h

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -195,12 +195,10 @@ class Peer : public std::enable_shared_from_this<Peer>,
195195
#endif
196196

197197
// Mutex to protect PeerState, which can be accessed and modified from
198-
// multiple threads
199-
#ifndef USE_TRACY
200-
RecursiveMutex mutable mStateMutex;
201-
#else
202-
mutable TracyLockable(std::recursive_mutex, mStateMutex);
203-
#endif
198+
// multiple threads.
199+
// LOCK ORDERING: mStateMutex must be acquired before Hmac::mMutex.
200+
mutable ANNOTATED_RECURSIVE_MUTEX(mStateMutex,
201+
ACQUIRED_BEFORE(Hmac::mMutex));
204202

205203
Hmac mHmac;
206204
// Does local node have capacity to read from this peer

0 commit comments

Comments
 (0)