summaryrefslogtreecommitdiff
path: root/src/mongo/db/exec/plan_stage.h
diff options
context:
space:
mode:
authorCharlie Swanson <charlie.swanson@mongodb.com>2017-04-05 11:35:23 -0400
committerCharlie Swanson <charlie.swanson@mongodb.com>2017-04-13 16:15:20 -0400
commitcc954e9e1d88b30d1ab89ee3bbbd9db0bb15263d (patch)
tree37df000f0d37d17bc82d5d1ad5436b4911249e4b /src/mongo/db/exec/plan_stage.h
parentb02b7f7bb78d4fd0bb006591769faaa216e6f8a7 (diff)
downloadmongo-cc954e9e1d88b30d1ab89ee3bbbd9db0bb15263d.tar.gz
SERVER-25694 Eliminate race in PlanExecutor cleanup.
Ensures that a collection lock is held in at least MODE_IS while deregistering a PlanExecutor from the cursor manager. Introduces new PlanExecutor::dispose() and ClientCursor::dispose() methods that must be called before destruction of those classes, and ensures they are called before destruction. These calls will thread an OperationContext all the way through to DocumentSource::dispose() for each stage in a Pipeline, which will give DocumentSourceCursor a chance to acquire locks and deregister its PlanExecutor if necessary.
Diffstat (limited to 'src/mongo/db/exec/plan_stage.h')
-rw-r--r--src/mongo/db/exec/plan_stage.h28
1 files changed, 28 insertions, 0 deletions
diff --git a/src/mongo/db/exec/plan_stage.h b/src/mongo/db/exec/plan_stage.h
index 6b3a67a2c04..33204c84839 100644
--- a/src/mongo/db/exec/plan_stage.h
+++ b/src/mongo/db/exec/plan_stage.h
@@ -261,6 +261,29 @@ public:
*/
void invalidate(OperationContext* opCtx, const RecordId& dl, InvalidationType type);
+ /*
+ * Releases any resources held by this stage. It is an error to use a PlanStage in any way after
+ * calling dispose(). Does not throw exceptions.
+ *
+ * Propagates to all children, then calls doDispose().
+ */
+ void dispose(OperationContext* opCtx) {
+ try {
+ // We may or may not be attached during disposal. We can't call
+ // reattachToOperationContext()
+ // directly, since that will assert that '_opCtx' is not set.
+ _opCtx = opCtx;
+ invariant(!_opCtx || opCtx == opCtx);
+
+ for (auto&& child : _children) {
+ child->dispose(opCtx);
+ }
+ doDispose();
+ } catch (...) {
+ std::terminate();
+ }
+ }
+
/**
* Retrieve a list of this stage's children. This stage keeps ownership of
* its children.
@@ -354,6 +377,11 @@ protected:
virtual void doReattachToOperationContext() {}
/**
+ * Does stage-specific destruction. Must not throw exceptions.
+ */
+ virtual void doDispose() {}
+
+ /**
* Does the stage-specific invalidation work.
*/
virtual void doInvalidate(OperationContext* opCtx, const RecordId& dl, InvalidationType type) {}