diff options
Diffstat (limited to 'Objects/object.c')
-rw-r--r-- | Objects/object.c | 17 |
1 files changed, 15 insertions, 2 deletions
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 |