-
-
Notifications
You must be signed in to change notification settings - Fork 30.6k
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
gh-117657: Make Py_TYPE and Py_SET_TYPE thread safe #120165
Conversation
Fidget-Spinner
commented
Jun 6, 2024
•
edited by bedevere-app
bot
Loading
edited by bedevere-app
bot
- Issue: Make TSAN tests pass with the GIL disabled in free-threaded builds #117657
Do you have a test / stack trace of the reported race? I don't think we should be modifying an object's type ( |
Example code: class Foo:
pass
class Bar:
pass
import threading
import os
X = Foo()
def work():
foo = X
for _ in range(10000):
foo.__class__ = Bar
type(foo)
foo.__class__ = Foo
type(foo)
threads = []
for i in range(os.cpu_count() - 1):
thread = threading.Thread(target=work)
thread.start()
threads.append(thread)
work()
for thread in threads:
thread.join() TSAN output:
Py_SET_TYPE:
|
Wow... the test case actually causes a segfault even with the fixes, not just a tsan warning. |
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.
LGTM.
Well, Py_TYPE() returns a borrow reference which is a bad thing :-/ But it shouldn't matter in this case, since the type is not deleted by the test. |
Can't merge this until we fix the actual crasher code #120198. It seems even default build is affected. |
Co-authored-by: Bénédikt Tran <[email protected]>
@@ -6630,12 +6630,18 @@ object_set_class(PyObject *self, PyObject *value, void *closure) | |||
return -1; | |||
} | |||
} | |||
Py_BEGIN_CRITICAL_SECTION(self); | |||
if (newto->tp_flags & Py_TPFLAGS_HEAPTYPE) { | |||
Py_INCREF(newto); |
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.
Is it important to do the INCREF(newto) and DECREF(oldto) inside the critical section?
Or it it possible to restrict the critical section to the following code?
oldto = Py_TYPE(self);
Py_SET_TYPE(self, newto);
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.
You're right. I can shrink it!
Co-Authored-By: Nadeshiko Manju <[email protected]>
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.
LGTM.
Since my previous review, object_set_class() got a critical section and it LGTM.
Thanks for the review Victor! |
Thanks @Fidget-Spinner for the PR 🌮🎉.. I'm working now to backport this PR to: 3.13. |
…20165) (cherry picked from commit e16aed6) Co-authored-by: Ken Jin <[email protected]> Co-authored-by: Bénédikt Tran <[email protected]> Co-authored-by: Nadeshiko Manju <[email protected]>
GH-120403 is a backport of this pull request to the 3.13 branch. |
GH-120403) gh-117657: Make Py_TYPE and Py_SET_TYPE thread safe (GH-120165) (cherry picked from commit e16aed6) Co-authored-by: Ken Jin <[email protected]> Co-authored-by: Bénédikt Tran <[email protected]> Co-authored-by: Nadeshiko Manju <[email protected]>
I think we should address
The thread-safety guarantees should be something like:
@Fidget-Spinner, would you like to work on this? |
@colesbury yeah I can revert the atomics in Py_TYPE and PY_SET_TYPE and stop the world instead. |
…20165) Co-authored-by: Bénédikt Tran <[email protected]> Co-authored-by: Nadeshiko Manju <[email protected]>
…20165) Co-authored-by: Bénédikt Tran <[email protected]> Co-authored-by: Nadeshiko Manju <[email protected]>
…20165) Co-authored-by: Bénédikt Tran <[email protected]> Co-authored-by: Nadeshiko Manju <[email protected]>