Uploaded image for project: 'Couchbase Server'
  1. Couchbase Server
  2. MB-32687

BP [6.0.2]: Connection::signalIfIdle may cause a deadlock when used from a different thread

    XMLWordPrintable

Details

    • Bug
    • Resolution: Fixed
    • Major
    • 6.0.2
    • 5.5.0, 5.5.1, 5.5.2, 6.0.0, 6.5.0
    • memcached
    • None
    • Triaged
    • Unknown

    Description

      The deadlock I encountered was when one thread was calling iterate_all_connections and trying to call signalIfIdle on a connection. It runs through all of the threads by first locking the thread, then locking the global connection structure (to ensure that the connections won't go away) and inspects all connections and calls the callback if it is bound to the locked worker thread. If the callback calls signalIfIdle we try to update the event mask for the connection to make sure that it is scheduled again. This calls tries to lock the event base for the connection...

      If that worker thread comes alive before the callback acquires the lock for the event base the worker thread will block trying to acquire the thread lock and we're in a deadlocked situation.

      (This will also break even more if other worker threads try to accept / close other connections as the connection mutex is locked so they'll also wait on the deadlocked thread).

       

      Suggestion: Refactor signalIfIdle to work the same way as notifyIoComplete (put it on the workerthreads list and tell the workerthread to process it).

      Attachments

        Issue Links

          For Gerrit Dashboard: MB-32687
          # Subject Branch Project Status CR V

          Activity

            People

              trond Trond Norbye
              trond Trond Norbye
              Votes:
              0 Vote for this issue
              Watchers:
              5 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:

                Gerrit Reviews

                  There are no open Gerrit changes

                  PagerDuty