There are two threads involved in Watcher.cc and Debounce.cc each
calling into respective methods of the other and thus each potentially
holding onto locks of the other. This can lead to a deadlock in the
following scenario:
While the Debounce.cc thread is processing callbacks in the
Debounce::notify() method, it holds its own lock. The method loops
over callbacks to process in Watcher.cc which itself requires a lock
in Watcher.cc. If an event gets reported while the debouncer is in
Watcher.triggerCallbacks(), a deadlock is present, because:
assume the event thread is thread A
assume the debouncer thread is thread B
A holds its own lock in Watcher::notify() and calls into
Debounce.trigger() which requires the debouncer lock
B at this time is inside Debounce::notify() holding its own lock
processing callbacks and about to call into Watcher.triggerCallbacks()
A deadlocks waiting for B to release the debouncer lock
B deadlocks waiting for A to release the watcher lock
fix https://github.com/parcel-bundler/watcher/issues/187
There are two threads involved in
Watcher.cc
andDebounce.cc
each calling into respective methods of the other and thus each potentially holding onto locks of the other. This can lead to a deadlock in the following scenario:While the
Debounce.cc
thread is processing callbacks in theDebounce::notify()
method, it holds its own lock. The method loops over callbacks to process inWatcher.cc
which itself requires a lock inWatcher.cc
. If an event gets reported while the debouncer is inWatcher.triggerCallbacks()
, a deadlock is present, because:Watcher::notify()
and calls intoDebounce.trigger()
which requires the debouncer lockDebounce::notify()
holding its own lock processing callbacks and about to call intoWatcher.triggerCallbacks()