[SERVER-25585] ClientCursor timeout logic can cause a hang. Created: 12/Aug/16  Updated: 02/Sep/16  Resolved: 19/Aug/16

Status: Closed
Project: Core Server
Component/s: Querying
Affects Version/s: 3.3.11
Fix Version/s: 3.3.12

Type: Bug Priority: Major - P3
Reporter: Robert Guo (Inactive) Assignee: Max Hirschhorn
Resolution: Done Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Depends
Related
is related to SERVER-25005 Execute queries in $lookup and $graph... Closed
Backwards Compatibility: Fully Compatible
Operating System: ALL
Sprint: Query 2016-08-29
Participants:
Linked BF Score: 0

 Description   

ClientCursor's destructor can try to acquire a mutex more than once, resulting in a hang.



 Comments   
Comment by Githook User [ 19/Aug/16 ]

Author:

{u'username': u'visemet', u'name': u'Max Hirschhorn', u'email': u'max.hirschhorn@mongodb.com'}

Message: SERVER-25585 Delete ClientCursors without holding _mutex to avoid hang.
Branch: master
https://github.com/mongodb/mongo/commit/98a26b4cff29549f4b779bf7c681f99b41dde710

Comment by Max Hirschhorn [ 12/Aug/16 ]

CursorManager::timeoutCursors() should destruct the ClientCursor while not holding the _mutex like CursorManager::eraseCursor() does because an aggregation cursor will call back into CursorManager::deregisterCursor().

Status CursorManager::eraseCursor(OperationContext* txn, CursorId id, bool shouldAudit) {
    ClientCursor* cursor;
 
    {
        stdx::lock_guard<SimpleMutex> lk(_mutex);
        ...
        cursor = it->second;
        ...
        cursor->kill();
        _deregisterCursor_inlock(cursor);
    }
 
    // If 'cursor' represents an aggregation cursor, then the destructor of the ClientCursor will
    // eventually cause the destructor of the underlying PlanExecutor to be called. Since the
    // underlying PlanExecutor is also registered on this CursorManager, we must destruct 'cursor'
    // without holding '_mutex' so that it's possible to call CursorManager::deregisterCursor()
    // without deadlocking ourselves.
    delete cursor;
    return Status::OK();
}

Generated at Thu Feb 08 04:09:37 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.