Bug report
Currently, there is a data race when PyDict_Watch/PyDict_Unwatch is called on a dict that another thread may concurrently mutate: the read of _ma_watcher_tag in _PyDict_NotifyEvent (on the mutation path) races with the modification by PyDict_Watch/PyDict_Unwatch. Additionally, concurrent PyDict_Watch/PyDict_Unwatch calls on the same dict (e.g. from different watcher IDs) race with each other, since both are non-atomic read-modify-write operations on _ma_watcher_tag.
In the free threading build, we should use atomic operations for the read of _ma_watcher_tag in _PyDict_NotifyEvent and for the updates performed by PyDict_Watch/PyDict_Unwatch.
Linked PRs
Bug report
Currently, there is a data race when
PyDict_Watch/PyDict_Unwatchis called on a dict that another thread may concurrently mutate: the read of_ma_watcher_tagin_PyDict_NotifyEvent(on the mutation path) races with the modification byPyDict_Watch/PyDict_Unwatch. Additionally, concurrentPyDict_Watch/PyDict_Unwatchcalls on the same dict (e.g. from different watcher IDs) race with each other, since both are non-atomic read-modify-write operations on_ma_watcher_tag.In the free threading build, we should use atomic operations for the read of
_ma_watcher_tagin_PyDict_NotifyEventand for the updates performed byPyDict_Watch/PyDict_Unwatch.Linked PRs