Skip to content

Commit fe3a29b

Browse files
authoredFeb 19, 2025··
Fix race in DownloadBucketsWork (#4651)
# Description Fixes a potential race in `DownloadBucketsWork`, where the parent `Work` could modify a map while the child `Work` on a potentially different thread held an iterator to that map. # Checklist - [x] Reviewed the [contributing](https://github.com/stellar/stellar-core/blob/master/CONTRIBUTING.md#submitting-changes) document - [x] Rebased on top of master (no merge commits) - [x] Ran `clang-format` v8.0.0 (via `make format` or the Visual Studio extension) - [x] Compiles - [x] Ran all tests - [ ] If change impacts performance, include supporting evidence per the [performance document](https://github.com/stellar/stellar-core/blob/master/performance-eval/performance-eval.md)
2 parents 6c8c90b + b71c807 commit fe3a29b

File tree

2 files changed

+11
-2
lines changed

2 files changed

+11
-2
lines changed
 

‎src/historywork/DownloadBucketsWork.cpp

+8-2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "work/WorkWithCallback.h"
1313
#include <Tracy.hpp>
1414
#include <fmt/format.h>
15+
#include <mutex>
1516

1617
namespace stellar
1718
{
@@ -92,7 +93,9 @@ DownloadBucketsWork::yieldMoreWork()
9293
std::static_pointer_cast<DownloadBucketsWork>(shared_from_this()));
9394

9495
auto currId = mIndexId++;
96+
mIndexMapMutex.lock();
9597
auto [indexIter, inserted] = mIndexMap.emplace(currId, nullptr);
98+
mIndexMapMutex.unlock();
9699
releaseAssertOrThrow(inserted);
97100

98101
auto successCb = [weak, ft, hash, currId](Application& app) -> bool {
@@ -102,17 +105,20 @@ DownloadBucketsWork::yieldMoreWork()
102105
// To avoid dangling references, maintain a map of index pointers
103106
// and do a lookup inside the callback instead of capturing anything
104107
// by reference.
108+
self->mIndexMapMutex.lock();
105109
auto indexIter = self->mIndexMap.find(currId);
106110
releaseAssertOrThrow(indexIter != self->mIndexMap.end());
107111
releaseAssertOrThrow(indexIter->second);
112+
auto index = std::move(indexIter->second);
113+
self->mIndexMap.erase(indexIter);
114+
self->mIndexMapMutex.unlock();
108115

109116
auto bucketPath = ft.localPath_nogz();
110117
auto b = app.getBucketManager().adoptFileAsBucket<LiveBucket>(
111118
bucketPath, hexToBin256(hash),
112119
/*mergeKey=*/nullptr,
113-
/*index=*/std::move(indexIter->second));
120+
/*index=*/std::move(index));
114121
self->mBuckets[hash] = b;
115-
self->mIndexMap.erase(currId);
116122
}
117123
return true;
118124
};

‎src/historywork/DownloadBucketsWork.h

+3
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ class DownloadBucketsWork : public BatchWork
2525

2626
// Store indexes of downloaded buckets
2727
std::map<int, std::unique_ptr<LiveBucketIndex const>> mIndexMap;
28+
29+
// Must be held when accessing mIndexMap
30+
std::mutex mIndexMapMutex;
2831
int mIndexId{0};
2932

3033
public:

0 commit comments

Comments
 (0)
Please sign in to comment.