summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregory Wlodarek <gregory.wlodarek@mongodb.com>2019-10-10 19:51:48 +0000
committerevergreen <evergreen@mongodb.com>2019-10-10 19:51:48 +0000
commitc4b5fd5f87de0ba8ffeaf86388f244a4a294c504 (patch)
tree2f71cd574058a86b3f32967cbac87d5fca0363b9
parentcfcdc9b9b84c3d9afcbb804513bbdbd54b77b7db (diff)
downloadmongo-c4b5fd5f87de0ba8ffeaf86388f244a4a294c504.tar.gz
SERVER-43886 Check if the index was dropped after locking the weak_ptr to the IndexCatalogEntry in RequiresIndexStage and RequiresAllIndicesStage
-rw-r--r--src/mongo/db/exec/requires_all_indices_stage.cpp3
-rw-r--r--src/mongo/db/exec/requires_all_indices_stage.h5
-rw-r--r--src/mongo/db/exec/requires_index_stage.cpp5
-rw-r--r--src/mongo/db/exec/requires_index_stage.h10
4 files changed, 11 insertions, 12 deletions
diff --git a/src/mongo/db/exec/requires_all_indices_stage.cpp b/src/mongo/db/exec/requires_all_indices_stage.cpp
index be26a5a0402..f96d4d2fc27 100644
--- a/src/mongo/db/exec/requires_all_indices_stage.cpp
+++ b/src/mongo/db/exec/requires_all_indices_stage.cpp
@@ -36,9 +36,10 @@ namespace mongo {
void RequiresAllIndicesStage::doRestoreStateRequiresCollection() {
size_t i = 0;
for (auto&& index : _indexCatalogEntries) {
+ auto indexCatalogEntry = index.lock();
uassert(ErrorCodes::QueryPlanKilled,
str::stream() << "query plan killed :: index '" << _indexNames[i] << "' dropped",
- index.lock());
+ indexCatalogEntry && !indexCatalogEntry->isDropped());
++i;
}
}
diff --git a/src/mongo/db/exec/requires_all_indices_stage.h b/src/mongo/db/exec/requires_all_indices_stage.h
index af70269e38f..68516960f3f 100644
--- a/src/mongo/db/exec/requires_all_indices_stage.h
+++ b/src/mongo/db/exec/requires_all_indices_stage.h
@@ -71,8 +71,9 @@ protected:
private:
// This stage holds weak pointers to all of the index catalog entries known at the time of
// construction. During yield recovery, we attempt to lock each weak pointer in order to
- // determine whether an index we rely on has been destroyed. If any index has been destroyed,
- // then we throw a query-fatal exception during restore.
+ // determine whether an index we rely on has been destroyed. If we can lock the weak pointer, we
+ // need to check the 'isDropped()' flag on the index catalog entry. If any index has been
+ // destroyed, then we throw a query-fatal exception during restore.
std::vector<std::weak_ptr<const IndexCatalogEntry>> _indexCatalogEntries;
// The names of the indices above. Used for error reporting.
diff --git a/src/mongo/db/exec/requires_index_stage.cpp b/src/mongo/db/exec/requires_index_stage.cpp
index 2ff0f373480..8e3e2382c9d 100644
--- a/src/mongo/db/exec/requires_index_stage.cpp
+++ b/src/mongo/db/exec/requires_index_stage.cpp
@@ -58,11 +58,12 @@ void RequiresIndexStage::doSaveStateRequiresCollection() {
void RequiresIndexStage::doRestoreStateRequiresCollection() {
// Attempt to lock the weak_ptr. If the resulting shared_ptr is null, then our index is no
- // longer valid and the query should die.
+ // longer valid and the query should die. We must also check the `isDropped()` flag on the index
+ // catalog entry if we are able lock the weak_ptr.
auto indexCatalogEntry = _weakIndexCatalogEntry.lock();
uassert(ErrorCodes::QueryPlanKilled,
str::stream() << "query plan killed :: index '" << _indexName << "' dropped",
- indexCatalogEntry);
+ indexCatalogEntry && !indexCatalogEntry->isDropped());
// Re-obtain catalog pointers that were set to null during yield preparation. It is safe to
// access the catalog entry by raw pointer when the query is active, as its validity is
diff --git a/src/mongo/db/exec/requires_index_stage.h b/src/mongo/db/exec/requires_index_stage.h
index fca94bf0de0..81d5649970e 100644
--- a/src/mongo/db/exec/requires_index_stage.h
+++ b/src/mongo/db/exec/requires_index_stage.h
@@ -82,17 +82,13 @@ protected:
}
private:
- // We keep a weak_ptr to the index catalog entry in order to detect when the underlying catalog
- // object has been destroyed, e.g. due to an index drop. In this scenario, the
- // RequiresIndexStage will throw a query-fatal exception after an attempt to lock the weak_ptr
- // indicates that the pointed-to object was deleted.
- //
// This is necessary to protect against that case that our index is dropped and then recreated
// during yield. Such an event should cause the query to be killed, since index cursors may have
// pointers into catalog objects that no longer exist. Since indices do not have UUIDs,
- // different epochs of the index cannot be distinguished. The weak_ptr allows us to safely.
+ // different epochs of the index cannot be distinguished. The weak_ptr allows us to safely
// determine whether the pointed-to object has been destroyed during yield recovery via the
- // shared_ptr control block.
+ // shared_ptr control block. We need to call `isDropped()` on the index catalog entry after
+ // locking the weak_ptr to determine whether the index was dropped or destructed during yield.
std::weak_ptr<const IndexCatalogEntry> _weakIndexCatalogEntry;
const IndexDescriptor* _indexDescriptor;