-
-
Notifications
You must be signed in to change notification settings - Fork 32.2k
GH-135106: Restrict trashcan to GC'ed objects #135682
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Objects/object.c
Outdated
@@ -3186,7 +3156,7 @@ _Py_Dealloc(PyObject *op) | |||
destructor dealloc = type->tp_dealloc; | |||
PyThreadState *tstate = _PyThreadState_GET(); | |||
intptr_t margin = _Py_RecursionLimit_GetMargin(tstate); | |||
if (margin < 2) { | |||
if (margin < 2 && PyObject_IS_GC(op)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you also need to guard the _PyTrash_thread_destroy_chain()
below; otherwise destructors for simple types (like PyLongObject
) can trigger arbitrary code execution.
That checks seems a bit more difficult to add efficiently.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
otherwise destructors for simple types (like PyLongObject) can trigger arbitrary code execution.
Does that matter?
We only care that PyStackRef_CLOSE_SPECIALIZED
doesn't escape and that doesn't (at least, shouldn't) call Py_DECREF
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PyStackRef_CLOSE_SPECIALIZED
callsPy_DECREF
in the free threaded build. This is fixable, but requires more changes.obj.attr += 1
wouldn't be atomic in the GIL-enabled build when using a lot of stack (already not atomic in free threaded build).- I think there are places in C code where we assume that
Py_DECREF()
on certain types of objects doesn't escape and won't invalidate borrowed references. One I encountered is:Line 9345 in 46c60e0
if (key != NULL && PyDict_DelItem(subclasses, key)) { PyLongObject
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can do it reasonably efficiently with a read of tp_flags
. Since we are reading tp_dealloc
anyway, the latency is likely hidden.
Objects/object.c
Outdated
} | ||
/* It is possible that the object has been accessed through | ||
* a weak ref, so only free if refcount == 0) */ | ||
if (Py_REFCNT(op) == 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you already brought this up in the meeting, but I don't think this should be necessary. Weakrefs won't resurrect an object with refcount of zero, which _PyTrash_thread_deposit_object()
ensures.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll put the assert back.
… and thread the trashcan list through the GC header
test_weakref.test_threaded_weak_key_dict_deepcopy
crash: merged objects should have ob_tid == 0 #135106