-
Notifications
You must be signed in to change notification settings - Fork 2.3k
Description
Summary
NotificationCenter methods call observer methods (start(), disable()) while holding the internal mutex, creating a lock-order-inversion with Observer's mutex.
Deadlock Scenario
Thread A (eg. SocketRreactor::run()):
Observer::notify()holds Observer mutex (M0)- Handler calls
removeEventHandler()(documented as safe) - →
hasObserver()waits for NotificationCenter mutex (M1)
Thread B (shutdown):
removeObserver()holds NotificationCenter mutex (M1)- →
disable()waits for Observer mutex (M0)
Result: Deadlock (M0 → M1, M1 → M0)
Affected Methods
addObserver()- callsstart()under lockremoveObserver()- callsdisable()under lockclear()- callsdisable()under lock
Fix
Release lock before calling observer methods:
void NotificationCenter::addObserver(const AbstractObserver& observer)
{
AbstractObserverPtr pObserver = observer.clone();
{
RWLock::ScopedWriteLock lock(_mutex);
_observers.push_back(pObserver);
}
// Start outside the lock to avoid deadlock with Observer mutex
pObserver->start();
}Reactions are currently unavailable