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

cursor may be deleted while in use by getMore()

    • Type: Icon: Bug Bug
    • Resolution: Done
    • Priority: Icon: Major - P3 Major - P3
    • 1.3.1
    • Affects Version/s: None
    • Component/s: None
    • None

      I'm trying to debug some issues that occur when we run our standard js tests in parallel. While looking at the code, I noticed the following:

      /* called every 4 seconds. millis is amount of idle time passed since the last call – could be zero */
      void ClientCursor::idleTimeReport(unsigned millis) {
      recursive_boostlock lock(ccmutex);
      for ( CCByLoc::iterator i = byLoc.begin(); i != byLoc.end(); ) {
      CCByLoc::iterator j = i;
      i++;
      if( j->second->shouldTimeout( millis ) )

      { log(1) << "killing old cursor " << j->second->cursorid << ' ' << j->second->ns << " idle:" << j->second->idleTime() << "ms\n"; delete j->second; }

      }
      }

      idleTimeReport() gets called with only a read lock in place, so it can happen in parallel with a getMore() request. getMore() grabs the client cursor mutex while it's finding a client cursor, but then it releases the client cursor mutex and continues to use the client cursor object it has found. I believe it's possible for idleTimeReport() to delete a getMore()'s client cursor after getMore() has looked up the client cursor but before getMore() has finished accessing the client cursor's attributes.

      I'm sorry I haven't written a test case - that's hard to do for a rare race condition like this.

            Assignee:
            dwight@mongodb.com Dwight Merriman
            Reporter:
            aaron Aaron Staple
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved: