Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork32k
Description
Crash report
What happened?
Playing with the code from#130148, I stumbled on a segfault in a free-threaded debug build with the following (seems to trigger faster/more consistently when pasted in the REPL):
fromcontextlibimportredirect_stdoutfromioimportStringIOfromthreadingimportThreadimporttimedeftest_redirect():text=StringIO()withredirect_stdout(text):print("hello1",file=text)time.sleep(0.1)print("hello2",file=text)print(text.getvalue())asserttext.getvalue()=="hello1\nhello2\n"forxinrange(100):Thread(target=test_redirect,args=()).start()
I didn't have time to check whether JIT, debug or no-gil are strictly necessary for this to crash. JIT is not needed for this to crash.
Cause
The problem is that in theprint()
implementation,_PySys_GetAttr
returns a borrowed reference.
Lines 2173 to 2175 in655fc8a
if (file==Py_None) { | |
PyThreadState*tstate=_PyThreadState_GET(); | |
file=_PySys_GetAttr(tstate,&_Py_ID(stdout)); |
So ifsys.stdout
changes concurrently with theprint()
, the program may crash becausefile
will point to a deallocated Python object.
This affects the GIL-enabled build as well. See this reproducer:https://gist.github.com/colesbury/c48f50e95d5d68e24814a56e2664e587
Suggested fix
Introduce a_PySys_GetAttrRef
that returns a new reference instead of a borrowed reference. Use that instead.
We should audit all the uses of_PySys_GetAttr
andPySys_GetObject
. I expect most of them will need to be replaced with functions that return new references, but it doesn't all have to be in a single PR.
CPython versions tested on:
CPython main branch
Operating systems tested on:
Linux
Output from running 'python -VV' on the command line:
Python 3.14.0a5+ experimental free-threading build (heads/main:359c7dde3bb, Feb 15 2025, 17:54:11) [GCC 11.4.0]
Linked PRs
- gh-130163: Fix usage of borrow references from _PySys_GetAttr #130282
- gh-130163: Fix possible crashes related to PySys_GetObject() #130503
- [3.13] gh-130163: Fix crashes related to PySys_GetObject() (GH-130503) #130556
- [3.13] gh-130163: Fix a leak in _pickle.c after backporting #130568
- [3.12] gh-130163: Fix crashes related to PySys_GetObject() (GH-130503) (GH-130556) #130576