Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Or at least, reduce the likelihood of it. We've seen deadlocks when GC runs while in the process of releasing an RLock; it results in a stack that looks like File ".../logging/__init__.py", line 232, in _releaseLock _lock.release() File ".../threading.py", line 189, in release self._block.release() File ".../eventlet/lock.py", line 24, in release return super(Lock, self).release(blocking=blocking) File ".../logging/__init__.py", line 831, in _removeHandlerRef acquire() File ".../logging/__init__.py", line 225, in _acquireLock _lock.acquire() That is, we try to release the lock, but in between clearing the RLock ownership information and releasing the underlying Lock, GC runs and invokes a weakref callback, which in turn tries to acquire the RLock. Since the ownership information has already been cleared, the lock's no longer re-entrant and everything seizes. This seems to have become more of a problem since we separated Lock and Semaphore; apparently the extra stack frame makes it much more likely that GC can sneak in during that critical moment. So, inline the release inside of Lock rather than punting to Semaphore; the implementation is simple anyway, and hasn't changed for at least 12 years (since Semaphore was pulled out to its own module). Closes #742
- Loading branch information