Skip to content

Commit 7190a2e

Browse files
committed
Merge branch 'main' into gh-115999-load-attr-instance-merged
2 parents 8b71951 + 8eebe4e commit 7190a2e

File tree

4 files changed

+37
-2
lines changed

4 files changed

+37
-2
lines changed

Lib/test/test_faulthandler.py

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import subprocess
88
import sys
99
from test import support
10-
from test.support import os_helper, script_helper, is_android, MS_WINDOWS
10+
from test.support import os_helper, script_helper, is_android, MS_WINDOWS, threading_helper
1111
import tempfile
1212
import unittest
1313
from textwrap import dedent
@@ -896,6 +896,34 @@ def test_cancel_later_without_dump_traceback_later(self):
896896
self.assertEqual(output, [])
897897
self.assertEqual(exitcode, 0)
898898

899+
@threading_helper.requires_working_threading()
900+
@unittest.skipUnless(support.Py_GIL_DISABLED, "only meaningful if the GIL is disabled")
901+
def test_free_threaded_dump_traceback(self):
902+
# gh-128400: Other threads need to be paused to invoke faulthandler
903+
code = dedent("""
904+
import faulthandler
905+
from threading import Thread, Event
906+
907+
class Waiter(Thread):
908+
def __init__(self):
909+
Thread.__init__(self)
910+
self.running = Event()
911+
self.stop = Event()
912+
913+
def run(self):
914+
self.running.set()
915+
self.stop.wait()
916+
917+
for _ in range(100):
918+
waiter = Waiter()
919+
waiter.start()
920+
waiter.running.wait()
921+
faulthandler.dump_traceback(all_threads=True)
922+
waiter.stop.set()
923+
waiter.join()
924+
""")
925+
_, exitcode = self.get_output(code)
926+
self.assertEqual(exitcode, 0)
899927

900928
if __name__ == "__main__":
901929
unittest.main()
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix crash when using :func:`faulthandler.dump_traceback` while other threads
2+
are active on the :term:`free threaded <free threading>` build.

Modules/faulthandler.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,12 @@ faulthandler_dump_traceback_py(PyObject *self,
237237
return NULL;
238238

239239
if (all_threads) {
240+
PyInterpreterState *interp = _PyInterpreterState_GET();
241+
/* gh-128400: Accessing other thread states while they're running
242+
* isn't safe if those threads are running. */
243+
_PyEval_StopTheWorld(interp);
240244
errmsg = _Py_DumpTracebackThreads(fd, NULL, tstate);
245+
_PyEval_StartTheWorld(interp);
241246
if (errmsg != NULL) {
242247
PyErr_SetString(PyExc_RuntimeError, errmsg);
243248
return NULL;

Objects/unicodeobject.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -688,7 +688,7 @@ _PyUnicode_CheckConsistency(PyObject *op, int check_content)
688688
|| kind == PyUnicode_2BYTE_KIND
689689
|| kind == PyUnicode_4BYTE_KIND);
690690
CHECK(ascii->state.ascii == 0);
691-
CHECK(compact->utf8 != data);
691+
CHECK(_PyUnicode_UTF8(op) != data);
692692
}
693693
else {
694694
PyUnicodeObject *unicode = _PyUnicodeObject_CAST(op);

0 commit comments

Comments
 (0)