@@ -1384,6 +1384,10 @@ free_work_item(uintptr_t ptr, delayed_dealloc_cb cb, void *state)
13841384 return ;
13851385 }
13861386 assert (_PyInterpreterState_GET ()-> stoptheworld .world_stopped );
1387+ if (_Py_IsImmortal (obj )) {
1388+ // The object may have become immortal after it was queued.
1389+ return ;
1390+ }
13871391 Py_ssize_t refcount = _Py_ExplicitMergeRefcount (obj , -1 );
13881392 if (refcount == 0 ) {
13891393 cb (obj , state );
@@ -1476,9 +1480,11 @@ free_delayed(uintptr_t ptr, size_t size)
14761480 _PyEval_StopTheWorld (tstate -> base .interp );
14771481 if (work_item_should_decref (ptr )) {
14781482 PyObject * obj = (PyObject * )(ptr - 1 );
1479- Py_ssize_t refcount = _Py_ExplicitMergeRefcount (obj , -1 );
1480- if (refcount == 0 ) {
1481- to_dealloc = obj ;
1483+ if (!_Py_IsImmortal (obj )) {
1484+ Py_ssize_t refcount = _Py_ExplicitMergeRefcount (obj , -1 );
1485+ if (refcount == 0 ) {
1486+ to_dealloc = obj ;
1487+ }
14821488 }
14831489 }
14841490 else {
@@ -1526,7 +1532,7 @@ void
15261532_PyObject_XDecRefDelayed (PyObject * ptr )
15271533{
15281534 assert (!((uintptr_t )ptr & 0x01 ));
1529- if (ptr != NULL ) {
1535+ if (ptr != NULL && ! _Py_IsImmortal ( ptr ) ) {
15301536 // We use 0 as the size since we don't have an easy way to know the
15311537 // actual size. If we are freeing many objects, the write sequence
15321538 // will be advanced due to QSBR_DEFERRED_LIMIT.
@@ -1541,12 +1547,7 @@ _PyObject_XSetRefDelayed(PyObject **ptr, PyObject *value)
15411547{
15421548 PyObject * old = * ptr ;
15431549 FT_ATOMIC_STORE_PTR_RELEASE (* ptr , value );
1544- if (old == NULL ) {
1545- return ;
1546- }
1547- if (!_Py_IsImmortal (old )) {
1548- _PyObject_XDecRefDelayed (old );
1549- }
1550+ _PyObject_XDecRefDelayed (old );
15501551}
15511552#endif
15521553
0 commit comments