What happened?
amber/src/main/python/core/util/thread/atomic.py::AtomicInteger.get_and_set acquires self._lock and then reads self.value. The value getter is a @property that also tries to acquire self._lock. The lock is a non-reentrant threading.Lock, so the second acquisition blocks forever — calling get_and_set deadlocks the calling thread the moment it is invoked.
The fix is either to switch the lock to threading.RLock, or to inline the read inside the existing critical section (old_value = self._value instead of old_value = self.value).
How to reproduce?
import threading
from core.util.thread.atomic import AtomicInteger
a = AtomicInteger(10)
done = threading.Event()
def attempt():
a.get_and_set(99)
done.set()
threading.Thread(target=attempt, daemon=True).start()
done.wait(timeout=0.5)
print(done.is_set()) # False — the call never returns
Version
1.1.0-incubating (Pre-release/Master)
What happened?
amber/src/main/python/core/util/thread/atomic.py::AtomicInteger.get_and_setacquiresself._lockand then readsself.value. Thevaluegetter is a@propertythat also tries to acquireself._lock. The lock is a non-reentrantthreading.Lock, so the second acquisition blocks forever — callingget_and_setdeadlocks the calling thread the moment it is invoked.The fix is either to switch the lock to
threading.RLock, or to inline the read inside the existing critical section (old_value = self._valueinstead ofold_value = self.value).How to reproduce?
Version
1.1.0-incubating (Pre-release/Master)