Uploaded image for project: 'Core Server'
  1. Core Server
  2. SERVER-39106

GlobalLock acquisition should throw when ticket acquisition times out if there is a max lock timeout and no deadline

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Closed
    • Priority: Major - P3
    • Resolution: Fixed
    • Affects Version/s: None
    • Fix Version/s: 4.0.7, 4.1.8
    • Component/s: Replication, Storage
    • Labels:
      None
    • Backwards Compatibility:
      Fully Compatible
    • Operating System:
      ALL
    • Backport Requested:
      v4.0
    • Sprint:
      Storage NYC 2019-02-11
    • Linked BF Score:
      69
    • Story Points:
      3

      Description

      If global lock acquisition times out acquiring a ticket, then the constructor will not throw, but the resource will be unlocked. This leads to invariant failure when we attempt to acquire the global lock here then call canAcceptWritesForDatabase() here, which invariants that the lock is held here.

      If the caller did not provide a deadline, then they are not checking for lock acquisition failure, so the lock acquisition should throw. Consider applying the following patch:

      diff --git a/src/mongo/db/concurrency/lock_state.cpp b/src/mongo/db/concurrency/lock_state.cpp
      index 11a4028..e7040b8 100644
      --- a/src/mongo/db/concurrency/lock_state.cpp
      +++ b/src/mongo/db/concurrency/lock_state.cpp
      @@ -353,6 +353,12 @@ LockResult LockerImpl::_lockGlobalBegin(OperationContext* opCtx, LockMode mode,
           dassert(isLocked() == (_modeForTicket != MODE_NONE));
           if (_modeForTicket == MODE_NONE) {
               auto acquireTicketResult = _acquireTicket(opCtx, mode, deadline);
      +        uassert(ErrorCodes::LockTimeout,
      +                str::stream() << "Unable to acquire ticket with mode '" << mode
      +                              << "' within a max lock request timeout of '"
      +                              << _maxLockTimeout.get()
      +                              << "' milliseconds.",
      +                acquireTicketResult == LOCK_OK || !_maxLockTimeout);
               if (acquireTicketResult != LOCK_OK) {
                   return acquireTicketResult;
               } 
      

        Attachments

          Issue Links

            Activity

              People

              • Votes:
                0 Vote for this issue
                Watchers:
                9 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved: