Skip to content
Merged
32 changes: 32 additions & 0 deletions Lib/test/_test_atexit.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,38 @@ def func():
finally:
atexit.unregister(func)

def test_eq_unregister_clear(self):
# Issue #112127: callback's __eq__ may call unregister or _clear
cnt = 0
class Func:
def __init__(self, action, eq_ret_val):
self.action = action
self.eq_ret_val = eq_ret_val

def __call__(self):
return

def __eq__(self, o):
nonlocal cnt
cnt += 1
Comment thread
benjaminJohnson2204 marked this conversation as resolved.
Outdated
if cnt == 1:
self.action(o)
return self.eq_ret_val(o)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

self.eq_ret_val is not callable.


for action in (
lambda o: atexit.unregister(self),
lambda o: atexit.unregister(o),
lambda o: atexit._clear()
):
for eq_ret_val in NotImplemented, True:
with self.subTest(action=action, eq_ret_val=eq_ret_val):
cnt = 0
f1 = Func(action, eq_ret_val)
f2 = Func(action, eq_ret_val)
atexit.register(f1)
atexit.register(f2)
atexit._run_exitfuncs()


if __name__ == "__main__":
unittest.main()
1 change: 1 addition & 0 deletions Misc/ACKS
Original file line number Diff line number Diff line change
Expand Up @@ -908,6 +908,7 @@ Jim Jewett
Pedro Diaz Jimenez
Orjan Johansen
Fredrik Johansson
Benjamin Johnson
Benjamin K. Johnson
Gregory K. Johnson
Kent Johnson
Expand Down
3 changes: 2 additions & 1 deletion Modules/atexitmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -257,10 +257,11 @@ static int
atexit_unregister_locked(PyObject *callbacks, PyObject *func)
{
for (Py_ssize_t i = 0; i < PyList_GET_SIZE(callbacks); ++i) {
PyObject *tuple = PyList_GET_ITEM(callbacks, i);
PyObject *tuple = Py_NewRef(PyList_GET_ITEM(callbacks, i));
assert(PyTuple_CheckExact(tuple));
PyObject *to_compare = PyTuple_GET_ITEM(tuple, 0);
int cmp = PyObject_RichCompareBool(func, to_compare, Py_EQ);
Py_DECREF(tuple);
if (cmp < 0)
{
return -1;
Expand Down
Loading