Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork33.7k
Description
Bug report
When calling finalizers from dealloc, we temporarily increase the refcount withPy_SET_REFCNT and then decrease it again (also withPy_SET_REFCNT). This isn't thread-safe in the free threading build because some other thread may concurrently try to increase the refcount during a racy dictionary or list access.
Lines 552 to 566 indabcecf
| /* Temporarily resurrect the object. */ | |
| Py_SET_REFCNT(self,1); | |
| PyObject_CallFinalizer(self); | |
| _PyObject_ASSERT_WITH_MSG(self, | |
| Py_REFCNT(self)>0, | |
| "refcount is too small"); | |
| /* Undo the temporary resurrection; can't use DECREF here, it would | |
| * cause a recursive call. */ | |
| Py_SET_REFCNT(self,Py_REFCNT(self)-1); | |
| if (Py_REFCNT(self)==0) { | |
| return0;/* this is the normal path out */ | |
| } |
We have similar issues with some watcher events:
Lines 1095 to 1102 indabcecf
| assert(Py_REFCNT(op)==0); | |
| Py_SET_REFCNT(op,1); | |
| handle_func_event(PyFunction_EVENT_DESTROY,op,NULL); | |
| if (Py_REFCNT(op)>1) { | |
| Py_SET_REFCNT(op,Py_REFCNT(op)-1); | |
| return; | |
| } | |
| Py_SET_REFCNT(op,0); |
This can lead to crashes when we have racy accesses to objects that may be concurrently finalized. For example:
./python -m test test_free_threading -m test_racing_load_super_attr -v -FTest (un)specialization of LOAD_SUPER_ATTR opcode. ... ./Include/internal/pycore_object.h:593: _Py_NegativeRefcount: Assertion failed: object has negative ref countEnable tracemalloc to get the memory block allocation traceback<object at 0x200041800f0 is freed>Fatal Python error: _PyObject_AssertFailed: _PyObject_AssertFailedPython runtime state: initialized(Observed more frequently on macOS, but also occurs on Linux)
In macOS buildbot:https://buildbot.python.org/#/builders/1368/builds/2251/steps/6/logs/stdio