-
Type:
Bug
-
Resolution: Unresolved
-
Priority:
Critical - P2
-
None
-
Affects Version/s: None
-
Component/s: None
-
DB Integration & Observability
-
ALL
-
-
None
-
None
-
None
-
None
-
None
-
None
-
None
Summary
An idle $search cursor opened with batchSize: 0 against a view (view definition contains $search) is not marked as holding the mongot task executor, so it is not disposed during shutdown. mongod then stalls for the full searchTaskExecutorShutdownTimeoutMS backstop (default 60s), or indefinitely if the timeout is disabled (0).
Background
SERVER-129849 added ClientCursorParams::mayHoldMongotTaskExecutor and disposes idle cursors holding mongot executor references before shutting down the search task executor. The flag is set in registerCursor() from aggExState.getOriginalLiteParsedPipeline().hasMongotStage() OR CurOp::debug().mongotCursorId.
Steps to reproduce
- Start mongod with a mongotmock host and searchTaskExecutorShutdownTimeoutMS=3000.
- Create a collection and a view whose definition is [{$search: {...}}].
- Run db.runCommand({aggregate: <view>, pipeline: [], cursor: {batchSize: 0)}}; it returns an empty first batch and a live cursor.
- MongoRunner.stopMongod(conn) without issuing a getMore.
Expected
Shutdown disposes the idle view cursor and completes promptly (< ~1s), as the direct-collection case does.
Actual
Shutdown waits out the executor timeout:
- disposeIdleMongotCursorsMillis: 0
- shutDownSearchTaskExecutorsMillis: 3002
- Log 12984901 "Timed out waiting for the search task executor to be destroyed during shutdown" at 3000ms
- Total shutdown ~3.8s
Control (direct collection, same pipeline, batchSize: 0) passes: shutdown ~710ms, disposeIdleMongotCursorsMillis: 1, no timeout.
Root cause
runAggregate resolves the main view and reassigns aggExState to a ResolvedViewAggExState (src/mongo/db/commands/query_cmd/run_aggregate.cpp:1643-1664). ResolvedViewAggExState overrides getOriginalLiteParsedPipeline() to return the caller's unexpanded pipeline (aggregation_execution_state.h:399) — the empty pipeline the user sent — not the resolved pipeline containing $search. So hasMongotStage() is false at run_aggregate.cpp:254. With batchSize: 0 the pipeline never executes, so OpDebug::mongotCursorId is also unset. Both detection paths miss, mayHoldMongotTaskExecutor stays false, and CursorManager::disposeIdleMongotCursorsForShutdown skips the cursor.
Impact
Any aggregation against a view that opens an idle search cursor can stall shutdown by the executor timeout (default 60s; hang if disabled). Reproduced on master (d008e6228f5) and on the v9.0/v8.3 backports.
Fix direction
Make the ownership check use the resolved/execution pipeline instead of getOriginalLiteParsedPipeline(). Add a regression test (view + $search + batchSize: 0 asserting prompt shutdown).
- is related to
-
SERVER-129849 Fix mongod shutdown hang waiting for search task executor
-
- Closed
-