Issue #13992: The trashcan mechanism is now thread-safe. This eliminates

sporadic crashes in multi-thread programs when several long deallocator
chains ran concurrently and involved subclasses of built-in container
types.

Note that the trashcan functions are part of the stable ABI, therefore
they have to be kept around for binary compatibility of extensions.
This commit is contained in:
Antoine Pitrou 2012-09-06 01:17:42 +02:00
commit 5b4faae307
7 changed files with 140 additions and 9 deletions

View file

@ -891,6 +891,7 @@ subtype_dealloc(PyObject *self)
{
PyTypeObject *type, *base;
destructor basedealloc;
PyThreadState *tstate = PyThreadState_GET();
/* Extract the type; we expect it to be a heap type */
type = Py_TYPE(self);
@ -940,8 +941,10 @@ subtype_dealloc(PyObject *self)
/* See explanation at end of function for full disclosure */
PyObject_GC_UnTrack(self);
++_PyTrash_delete_nesting;
++ tstate->trash_delete_nesting;
Py_TRASHCAN_SAFE_BEGIN(self);
--_PyTrash_delete_nesting;
-- tstate->trash_delete_nesting;
/* DO NOT restore GC tracking at this point. weakref callbacks
* (if any, and whether directly here or indirectly in something we
* call) may trigger GC, and if self is tracked at that point, it
@ -1020,8 +1023,10 @@ subtype_dealloc(PyObject *self)
endlabel:
++_PyTrash_delete_nesting;
++ tstate->trash_delete_nesting;
Py_TRASHCAN_SAFE_END(self);
--_PyTrash_delete_nesting;
-- tstate->trash_delete_nesting;
/* Explanation of the weirdness around the trashcan macros: