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

mapReduce unsafely disposes of its PlanExecutor

    • Type: Icon: Bug Bug
    • Resolution: Fixed
    • Priority: Icon: Major - P3 Major - P3
    • 3.6.0-rc4
    • Affects Version/s: 3.6.0-rc2
    • Component/s: MapReduce, Querying
    • Labels:
      None
    • Fully Compatible
    • ALL
    • Query 2017-11-13
    • 0

      The PlanExecutor created by the mapReduce command here is managed by the collection over which the mapReduce is running. This means that a lock on the collection must be held while the PlanExecutor is being disposed, so that deregistration of the executor is synchronized correctly with catalog-level events such as collection drops. The following dassert() checks that the correct locks are held in debug builds:

      https://github.com/mongodb/mongo/blob/dc04d7d6f22e6542f9f20cf33cd40015cefcf530/src/mongo/db/query/plan_executor.cpp#L653

      The mapReduce code holds the proper locks for most of its execution, but these locks are temporarily released in order to perform the reduce step. It is possible for an exception to be thrown by
      State::reduceAndSpillInMemoryStateIfNeeded(), in which case the PlanExecutor will be incorrectly disposed out of the lock.

      Our continuous integration testing has caught this specifically in the case of a mapReduce running while the mongod is shutting down, since this causes State::reduceAndSpillInMemoryStateIfNeeded() to throw with an InterruptedAtShutdown error. The result is an invariant() failure in a debug build, though the system could also crash in a non-debug build due to using a Collection object that has been freed.

            Assignee:
            david.storch@mongodb.com David Storch
            Reporter:
            david.storch@mongodb.com David Storch
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved: