The aggregation subsystem may invoke the underlying multi-planning system multiple times in order to select its execution plan. For example, when there is a $sort it first attempts to construct a non-blocking $sort plan. If no such plan exists, it then invokes the plan selection code again without pushing down the $sort to the underlying PlanStage layer. See the code implementing this logic here.
If during this process the operation is killed—because the client disconnected, or due to an explicit killOp command, or due to a conflicting catalog event such as a collection drop—then this process should terminate at the next yield point and the operation should stop running. However, there is incorrect logic that accidentally swallows the interruption error and attempts to keep executing the aggregation operation. Specifically, we have checks to propagate the error code QueryPlanKilled which misses other possible error codes, e.g. ClientDisconnect.
Since an interrupt check happens at query yield points, the interruption error is propagated after locks have been relinquished. The consequence is that we attempt to keep executing the aggregation operation without holding the proper locks. This promptly triggers the following server-fatal invariant check, which makes an assertion that the necessary locks are held:
When this scenario occurs, the server will shut down and and the logs will contain the following message, along with a backtrace:
2019-09-06T13:37:05.575-0400 F - [conn1] Invariant failure opCtx->lockState()->isDbLockedForMode(db, MODE_IS) || (db.compare("local") == 0 && opCtx->lockState()->isLocked()) src/mongo/db/catalog/database_holder_impl.cpp 74
- duplicates
-
SERVER-55247 Invariant failure opCtx->lockState()->isDbLockedForMode(db, MODE_IS)
- Closed
- is related to
-
SERVER-55247 Invariant failure opCtx->lockState()->isDbLockedForMode(db, MODE_IS)
- Closed
- related to
-
SERVER-24198 When planning fails because there is no way to answer the query, it should emit ErrorCodes::NoQueryExecutionPlans
- Closed