Skip to content

Commit b874f0b

Browse files
implement PyUnstable_SetImmortal
1 parent 638d22c commit b874f0b

File tree

4 files changed

+44
-0
lines changed

4 files changed

+44
-0
lines changed

Doc/c-api/object.rst

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -801,3 +801,19 @@ Object Protocol
801801
cannot fail.
802802
803803
.. versionadded:: 3.14
804+
805+
.. c:function:: int PyUnstable_SetImmortal(PyObject *obj)
806+
807+
Marks the object op immortal. The argument should be uniquely referenced by
808+
the calling thread.
809+
810+
This is a one-way process: objects can only be made immortal, they cannot be
811+
made mortal once again. Immortal objects do not participate in reference counting
812+
and will never be garbage collected.
813+
814+
This function is intended to be used soon after op is created, by the code that
815+
creates it, such as in the object's tp_new slot.
816+
Returns 1 if the object was made immortal and returns 0 if it was not.
817+
This function cannot fail.
818+
819+
.. versionadded:: next

Include/cpython/object.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -493,3 +493,5 @@ PyAPI_FUNC(int) PyUnstable_TryIncRef(PyObject *);
493493
PyAPI_FUNC(void) PyUnstable_EnableTryIncRef(PyObject *);
494494

495495
PyAPI_FUNC(int) PyUnstable_Object_IsUniquelyReferenced(PyObject *);
496+
497+
PyAPI_FUNC(int) PyUnstable_SetImmortal(PyObject *op);

Modules/_testcapi/object.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,23 @@ 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
210+
PyObject object = {
211+
.ob_refcnt = 1,
212+
.ob_type = &PyBaseObject_Type,
213+
};
214+
assert(!PyUnstable_IsImmortal(&object));
215+
PyUnstable_SetImmortal(&object);
216+
assert(PyUnstable_IsImmortal(&object));
217+
Py_DECREF(&object); // should not dealloc
218+
assert(PyUnstable_IsImmortal(&object));
219+
Py_RETURN_NONE;
220+
}
204221

205222
static PyObject *
206223
_test_incref(PyObject *ob)
@@ -528,6 +545,7 @@ static PyMethodDef test_methods[] = {
528545
{"pyobject_is_unique_temporary", pyobject_is_unique_temporary, METH_O},
529546
{"pyobject_is_unique_temporary_new_object", pyobject_is_unique_temporary_new_object, METH_NOARGS},
530547
{"test_py_try_inc_ref", test_py_try_inc_ref, METH_NOARGS},
548+
{"test_py_set_immortal", test_py_set_immortal, METH_NOARGS},
531549
{"test_xincref_doesnt_leak",test_xincref_doesnt_leak, METH_NOARGS},
532550
{"test_incref_doesnt_leak", test_incref_doesnt_leak, METH_NOARGS},
533551
{"test_xdecref_doesnt_leak",test_xdecref_doesnt_leak, METH_NOARGS},

Objects/object.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2790,6 +2790,14 @@ PyUnstable_EnableTryIncRef(PyObject *op)
27902790
#endif
27912791
}
27922792

2793+
int
2794+
PyUnstable_SetImmortal(PyObject *op)
2795+
{
2796+
assert(op != NULL);
2797+
_Py_SetImmortal(op);
2798+
return 1;
2799+
}
2800+
27932801
void
27942802
_Py_ResurrectReference(PyObject *op)
27952803
{

0 commit comments

Comments
 (0)