@@ -201,6 +201,44 @@ test_py_try_inc_ref(PyObject *self, PyObject *unused)
201201 Py_RETURN_NONE ;
202202}
203203
204+ static PyObject *
205+ test_py_set_immortal (PyObject * self , PyObject * unused )
206+ {
207+ // the object is allocated on C stack as otherwise,
208+ // it would trip the refleak checker when the object
209+ // is made immortal and leak memory, for the same
210+ // reason we cannot call PyObject_Init() on it.
211+ PyObject object = {0 };
212+ #ifdef Py_GIL_DISABLED
213+ object .ob_tid = _Py_ThreadId ();
214+ object .ob_gc_bits = 0 ;
215+ object .ob_ref_local = 1 ;
216+ object .ob_ref_shared = 0 ;
217+ #else
218+ object .ob_refcnt = 1 ;
219+ #endif
220+ object .ob_type = & PyBaseObject_Type ;
221+
222+ assert (!PyUnstable_IsImmortal (& object ));
223+ int rc = PyUnstable_SetImmortal (& object );
224+ assert (rc == 1 );
225+ assert (PyUnstable_IsImmortal (& object ));
226+ Py_DECREF (& object ); // should not dealloc
227+ assert (PyUnstable_IsImmortal (& object ));
228+
229+ // Check already immortal object
230+ rc = PyUnstable_SetImmortal (& object );
231+ assert (rc == 0 );
232+
233+ // Check unicode objects
234+ PyObject * unicode = PyUnicode_FromString ("test" );
235+ assert (!PyUnstable_IsImmortal (unicode ));
236+ rc = PyUnstable_SetImmortal (unicode );
237+ assert (rc == 0 );
238+ assert (!PyUnstable_IsImmortal (unicode ));
239+ Py_DECREF (unicode );
240+ Py_RETURN_NONE ;
241+ }
204242
205243static PyObject *
206244_test_incref (PyObject * ob )
@@ -528,6 +566,7 @@ static PyMethodDef test_methods[] = {
528566 {"pyobject_is_unique_temporary" , pyobject_is_unique_temporary , METH_O },
529567 {"pyobject_is_unique_temporary_new_object" , pyobject_is_unique_temporary_new_object , METH_NOARGS },
530568 {"test_py_try_inc_ref" , test_py_try_inc_ref , METH_NOARGS },
569+ {"test_py_set_immortal" , test_py_set_immortal , METH_NOARGS },
531570 {"test_xincref_doesnt_leak" ,test_xincref_doesnt_leak , METH_NOARGS },
532571 {"test_incref_doesnt_leak" , test_incref_doesnt_leak , METH_NOARGS },
533572 {"test_xdecref_doesnt_leak" ,test_xdecref_doesnt_leak , METH_NOARGS },
0 commit comments