summaryrefslogtreecommitdiff
path: root/Objects/object.c
diff options
context:
space:
mode:
Diffstat (limited to 'Objects/object.c')
-rw-r--r--Objects/object.c17
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