summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Larkin-York <dan.larkin-york@mongodb.com>2021-03-04 22:04:44 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-03-05 19:15:45 +0000
commit7676194fd8a363c7c9f3099e814dc71bbe401efb (patch)
tree65b8feff9e39c7a02b19a66e4a8c6d5651eed267
parent36597e8ce4fcf00e777bca348929c1530a79c699 (diff)
downloadmongo-7676194fd8a363c7c9f3099e814dc71bbe401efb.tar.gz
SERVER-54922 Fix broken promises resulting from concurrency issue in BucketCatalog::clear
-rw-r--r--src/mongo/db/timeseries/bucket_catalog.cpp26
-rw-r--r--src/mongo/db/timeseries/bucket_catalog.h1
2 files changed, 19 insertions, 8 deletions
diff --git a/src/mongo/db/timeseries/bucket_catalog.cpp b/src/mongo/db/timeseries/bucket_catalog.cpp
index 06a9c71985d..b5b01b68631 100644
--- a/src/mongo/db/timeseries/bucket_catalog.cpp
+++ b/src/mongo/db/timeseries/bucket_catalog.cpp
@@ -320,17 +320,23 @@ void BucketCatalog::clear(const BucketId& bucketId) {
return;
}
- while (!bucket->promises.empty()) {
- if (auto& promise = bucket->promises.front()) {
- promise->setError({ErrorCodes::TimeseriesBucketCleared,
- str::stream() << "Time-series bucket " << *bucketId << " for "
- << bucket->ns << " was cleared"});
+ // Retain pointer to bucket, release so we can get an exclusive lock.
+ std::shared_ptr<Bucket> underlyingBucket{bucket};
+ bucket.release();
+ auto lk = _lockExclusive();
+
+ {
+ stdx::lock_guard blk{underlyingBucket->lock};
+ while (!underlyingBucket->promises.empty()) {
+ if (auto& promise = underlyingBucket->promises.front()) {
+ promise->setError({ErrorCodes::TimeseriesBucketCleared,
+ str::stream() << "Time-series bucket " << *bucketId << " for "
+ << underlyingBucket->ns << " was cleared"});
+ }
+ underlyingBucket->promises.pop();
}
- bucket->promises.pop();
}
- bucket.release();
- auto lk = _lockExclusive();
_removeBucket(bucketId);
}
@@ -652,6 +658,10 @@ BucketCatalog::BucketAccess::operator bool() const {
return isLocked();
}
+BucketCatalog::BucketAccess::operator std::shared_ptr<BucketCatalog::Bucket>() const {
+ return _bucket;
+}
+
void BucketCatalog::BucketAccess::rollover(const std::function<bool(BucketAccess*)>& isBucketFull) {
invariant(isLocked());
invariant(_key);
diff --git a/src/mongo/db/timeseries/bucket_catalog.h b/src/mongo/db/timeseries/bucket_catalog.h
index ad7e5740d48..66f8d493cc8 100644
--- a/src/mongo/db/timeseries/bucket_catalog.h
+++ b/src/mongo/db/timeseries/bucket_catalog.h
@@ -388,6 +388,7 @@ private:
bool isLocked() const;
Bucket* operator->();
operator bool() const;
+ operator std::shared_ptr<Bucket>() const;
// Release the bucket lock, typically in order to reacquire the catalog lock.
void release();