[3.9] bpo-40826: Fix GIL usage in PyOS_Readline() (GH-20613) (GH-20616)
* bpo-40826: Fix GIL usage in PyOS_Readline() (GH-20579)
Fix GIL usage in PyOS_Readline(): lock the GIL to set an exception.
Pass tstate to my_fgets() and _PyOS_WindowsConsoleReadline(). Cleanup
these functions.
(cherry picked from commit c353764fd564e401cf47a5d9efab18c72c60014e)
* bpo-40826: Add _PyOS_InterruptOccurred(tstate) function (GH-20599)
my_fgets() now calls _PyOS_InterruptOccurred(tstate) to check for
pending signals, rather calling PyOS_InterruptOccurred().
my_fgets() is called with the GIL released, whereas
PyOS_InterruptOccurred() must be called with the GIL held.
test_repl: use text=True and avoid SuppressCrashReport in
test_multiline_string_parsing().
Fix my_fgets() on Windows: fgets(fp) does crash if fileno(fp) is closed.
(cherry picked from commit fa7ab6aa0f9a4f695e5525db5a113cd21fa93787)
diff --git a/Modules/signalmodule.c b/Modules/signalmodule.c
index 0c9a267..119fc35 100644
--- a/Modules/signalmodule.c
+++ b/Modules/signalmodule.c
@@ -187,14 +187,20 @@
#endif
static int
-is_main(_PyRuntimeState *runtime)
+is_main_interp(_PyRuntimeState *runtime, PyInterpreterState *interp)
{
unsigned long thread = PyThread_get_thread_ident();
- PyInterpreterState *interp = _PyRuntimeState_GetThreadState(runtime)->interp;
return (thread == runtime->main_thread
&& interp == runtime->interpreters.main);
}
+static int
+is_main(_PyRuntimeState *runtime)
+{
+ PyInterpreterState *interp = _PyRuntimeState_GetThreadState(runtime)->interp;
+ return is_main_interp(runtime, interp);
+}
+
static PyObject *
signal_default_int_handler(PyObject *self, PyObject *args)
{
@@ -1726,12 +1732,14 @@
finisignal();
}
+
+// The caller doesn't have to hold the GIL
int
-PyOS_InterruptOccurred(void)
+_PyOS_InterruptOccurred(PyThreadState *tstate)
{
if (_Py_atomic_load_relaxed(&Handlers[SIGINT].tripped)) {
_PyRuntimeState *runtime = &_PyRuntime;
- if (!is_main(runtime)) {
+ if (!is_main_interp(runtime, tstate->interp)) {
return 0;
}
_Py_atomic_store_relaxed(&Handlers[SIGINT].tripped, 0);
@@ -1740,6 +1748,16 @@
return 0;
}
+
+// The caller must to hold the GIL
+int
+PyOS_InterruptOccurred(void)
+{
+ PyThreadState *tstate = _PyThreadState_GET();
+ return _PyOS_InterruptOccurred(tstate);
+}
+
+
static void
_clear_pending_signals(void)
{