From a66f9c6bb134561a24374f10e8c35417d356ce14 Mon Sep 17 00:00:00 2001 From: Xiang Zhang Date: Sat, 13 May 2017 13:36:14 +0800 Subject: bpo-30341: Improve _PyTrash_thread_destroy_chain() a little bit (#1545) * add a comment about why we need to increase trash_delete_nesting * move increase and decrese outside of the loop --- Objects/object.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'Objects/object.c') diff --git a/Objects/object.c b/Objects/object.c index 2d79e2f9c1..2ba6e572ea 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -2093,6 +2093,19 @@ void _PyTrash_thread_destroy_chain(void) { PyThreadState *tstate = PyThreadState_GET(); + /* We need to increase trash_delete_nesting here, otherwise, + _PyTrash_thread_destroy_chain will be called recursively + and then possibly crash. An example that may crash without + increase: + N = 500000 # need to be large enough + ob = object() + tups = [(ob,) for i in range(N)] + for i in range(49): + tups = [(tup,) for tup in tups] + del tups + */ + assert(tstate->trash_delete_nesting == 0); + ++tstate->trash_delete_nesting; while (tstate->trash_delete_later) { PyObject *op = tstate->trash_delete_later; destructor dealloc = Py_TYPE(op)->tp_dealloc; @@ -2107,10 +2120,10 @@ _PyTrash_thread_destroy_chain(void) * up distorting allocation statistics. */ assert(op->ob_refcnt == 0); - ++tstate->trash_delete_nesting; (*dealloc)(op); - --tstate->trash_delete_nesting; + assert(tstate->trash_delete_nesting == 1); } + --tstate->trash_delete_nesting; } #ifndef Py_TRACE_REFS -- cgit v1.2.1