ClusterCursorManager::killCursorsWithMatchingSessions() creates a lambda which makes a call to ClusterCursorManager::getNamespaceForCursorId(). This function returns a boost::optional<NamespaceString> which may be boost::none. However, the lambda calls get() on it unconditionally:
In debug builds, this trips a process-fatal assertion. In non-debug builds it leads to undefined behavior.
This situation can occur because the killCursorsWithMatchingSessions() makes several different calls into the mongos cursor manager, which acquire the cursor manager mutex independently. First, it uses getCursorsForSession() to gather up the cursors associated with a logical session. Next, after dropping and requiring the mutex, it calls getNamespaceForCursorId() in the process of killing these cursors. If in between these two steps, all of the cursors for one of the relevant namespaces die, then getNamespaceForCursorId() will no longer be tracking the namespace and will return boost::none. In the repro steps, this is achieved by issuing a killCursors command concurrently with a killSessions command.