Blame SOURCES/gdb-rhbz1829702-fix-python39.patch

9093b4
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
9093b4
From: Keith Seitz <keiths@redhat.com>
9093b4
Date: Thu, 4 Jun 2020 17:16:48 -0700
9093b4
Subject: gdb-rhbz1829702-fix-python39.patch
9093b4
9093b4
;; Backport "Fix Python 3.9 related runtime problems"
9093b4
;; Kevin Buettner <kevinb@redhat.com> and Keith Seitz <keiths@redhat.com>
9093b4
9093b4
commit c47bae859a5af0d95224d90000df0e529f7c5aa0
9093b4
Author: Kevin Buettner <kevinb@redhat.com>
9093b4
Date:   Wed May 27 20:05:40 2020 -0700
9093b4
9093b4
    Fix Python3.9 related runtime problems
9093b4
9093b4
    Python3.9b1 is now available on Rawhide.  GDB w/ Python 3.9 support
9093b4
    can be built using the configure switch -with-python=/usr/bin/python3.9.
9093b4
9093b4
    Attempting to run gdb/Python3.9 segfaults on startup:
9093b4
9093b4
        #0  0x00007ffff7b0582c in PyEval_ReleaseLock () from /lib64/libpython3.9
9093b4
.so.1.0
9093b4
        #1  0x000000000069ccbf in do_start_initialization ()
9093b4
            at worktree-test1/gdb/python/python.c:1789
9093b4
        #2  _initialize_python ()
9093b4
            at worktree-test1/gdb/python/python.c:1877
9093b4
        #3  0x00000000007afb0a in initialize_all_files () at init.c:237
9093b4
        ...
9093b4
9093b4
    Consulting the the documentation...
9093b4
9093b4
    https://docs.python.org/3/c-api/init.html
9093b4
9093b4
    ...we find that PyEval_ReleaseLock() has been deprecated since version
9093b4
    3.2.  It recommends using PyEval_SaveThread or PyEval_ReleaseThread()
9093b4
    instead.  In do_start_initialization, in gdb/python/python.c, we
9093b4
    can replace the calls to PyThreadState_Swap() and PyEval_ReleaseLock()
9093b4
    with a single call to PyEval_SaveThread.   (Thanks to Keith Seitz
9093b4
    for working this out.)
9093b4
9093b4
    With that in place, GDB gets a little bit further.  It still dies
9093b4
    on startup, but the backtrace is different:
9093b4
9093b4
        #0  0x00007ffff7b04306 in PyOS_InterruptOccurred ()
9093b4
           from /lib64/libpython3.9.so.1.0
9093b4
        #1  0x0000000000576e86 in check_quit_flag ()
9093b4
            at worktree-test1/gdb/extension.c:776
9093b4
        #2  0x0000000000576f8a in set_active_ext_lang (now_active=now_active@entry=0x983c00 <extension_language_python>)
9093b4
            at worktree-test1/gdb/extension.c:705
9093b4
        #3  0x000000000069d399 in gdbpy_enter::gdbpy_enter (this=0x7fffffffd2d0,
9093b4
            gdbarch=0x0, language=0x0)
9093b4
            at worktree-test1/gdb/python/python.c:211
9093b4
        #4  0x0000000000686e00 in python_new_inferior (inf=0xddeb10)
9093b4
            at worktree-test1/gdb/python/py-inferior.c:251
9093b4
        #5  0x00000000005d9fb9 in std::function<void (inferior*)>::operator()(inferior*) const (__args#0=<optimized out>, this=0xccad20)
9093b4
            at /usr/include/c++/10/bits/std_function.h:617
9093b4
        #6  gdb::observers::observable<inferior*>::notify (args#0=0xddeb10,
9093b4
            this=<optimized out>)
9093b4
            at worktree-test1/gdb/../gdbsupport/observable.h:106
9093b4
        #7  add_inferior_silent (pid=0)
9093b4
            at worktree-test1/gdb/inferior.c:113
9093b4
        #8  0x00000000005dbcb8 in initialize_inferiors ()
9093b4
            at worktree-test1/gdb/inferior.c:947
9093b4
        ...
9093b4
9093b4
    We checked with some Python Developers and were told that we should
9093b4
    acquire the GIL prior to calling any Python C API function.  We
9093b4
    definitely don't have the GIL for calls of PyOS_InterruptOccurred().
9093b4
9093b4
    I moved class_gdbpy_gil earlier in the file and use it in
9093b4
    gdbpy_check_quit_flag() to acquire (and automatically release) the
9093b4
    GIL.
9093b4
9093b4
    With those changes in place, I was able to run to a GDB prompt.  But,
9093b4
    when trying to quit, it segfaulted again due to due to some other
9093b4
    problems with gdbpy_check_quit_flag():
9093b4
9093b4
        Thread 1 "gdb" received signal SIGSEGV, Segmentation fault.
9093b4
        0x00007ffff7bbab0c in new_threadstate () from /lib64/libpython3.9.so.1.0
9093b4
        (top-gdb) bt 8
9093b4
        #0  0x00007ffff7bbab0c in new_threadstate () from /lib64/libpython3.9.so.1.0
9093b4
        #1  0x00007ffff7afa5ea in PyGILState_Ensure.cold ()
9093b4
           from /lib64/libpython3.9.so.1.0
9093b4
        #2  0x000000000069b58c in gdbpy_gil::gdbpy_gil (this=<synthetic pointer>)
9093b4
            at worktree-test1/gdb/python/python.c:278
9093b4
        #3  gdbpy_check_quit_flag (extlang=<optimized out>)
9093b4
            at worktree-test1/gdb/python/python.c:278
9093b4
        #4  0x0000000000576e96 in check_quit_flag ()
9093b4
            at worktree-test1/gdb/extension.c:776
9093b4
        #5  0x000000000057700c in restore_active_ext_lang (previous=0xe9c050)
9093b4
            at worktree-test1/gdb/extension.c:729
9093b4
        #6  0x000000000088913a in do_my_cleanups (
9093b4
            pmy_chain=0xc31870 <final_cleanup_chain>,
9093b4
            old_chain=0xae5720 <sentinel_cleanup>)
9093b4
            at worktree-test1/gdbsupport/cleanups.cc:131
9093b4
        #7  do_final_cleanups ()
9093b4
            at worktree-test1/gdbsupport/cleanups.cc:143
9093b4
9093b4
    In this case, we're trying to call a Python C API function after
9093b4
    Py_Finalize() has been called from finalize_python().  I made
9093b4
    finalize_python set gdb_python_initialized to false and then cause
9093b4
    check_quit_flag() to return early when it's false.
9093b4
9093b4
    With these changes in place, GDB seems to be working again with
9093b4
    Python3.9b1.  I think it likely that there are other problems lurking.
9093b4
    I wouldn't be surprised to find that there are other calls into Python
9093b4
    where we don't first make sure that we have the GIL.  Further changes
9093b4
    may well be needed.
9093b4
9093b4
    I see no regressions testing on Rawhide using a GDB built with the
9093b4
    default Python version (3.8.3) versus one built using Python 3.9b1.
9093b4
9093b4
    I've also tested on Fedora 28, 29, 30, 31, and 32 (all x86_64) using
9093b4
    the default (though updated) system installed versions of Python on
9093b4
    those OSes.  This means that I've tested against Python versions
9093b4
    2.7.15, 2.7.17, 2.7.18, 3.7.7, 3.8.2, and 3.8.3.  In each case GDB
9093b4
    still builds without problem and shows no regressions after applying
9093b4
    this patch.
9093b4
9093b4
    gdb/ChangeLog:
9093b4
9093b4
    2020-MM-DD  Kevin Buettner  <kevinb@redhat.com>
9093b4
                Keith Seitz  <keiths@redhat.com>
9093b4
9093b4
            * python/python.c (do_start_initialization): For Python 3.9 and
9093b4
            later, call PyEval_SaveThread instead of PyEval_ReleaseLock.
9093b4
            (class gdbpy_gil): Move to earlier in file.
9093b4
            (finalize_python): Set gdb_python_initialized.
9093b4
            (gdbpy_check_quit_flag): Acquire GIL via gdbpy_gil.  Return early
9093b4
            when not initialized.
9093b4
9093b4
diff --git a/gdb/python/python.c b/gdb/python/python.c
9093b4
--- a/gdb/python/python.c
9093b4
+++ b/gdb/python/python.c
9093b4
@@ -234,6 +234,30 @@ gdbpy_enter::~gdbpy_enter ()
9093b4
   PyGILState_Release (m_state);
9093b4
 }
9093b4
 
9093b4
+/* A helper class to save and restore the GIL, but without touching
9093b4
+   the other globals that are handled by gdbpy_enter.  */
9093b4
+
9093b4
+class gdbpy_gil
9093b4
+{
9093b4
+public:
9093b4
+
9093b4
+  gdbpy_gil ()
9093b4
+    : m_state (PyGILState_Ensure ())
9093b4
+  {
9093b4
+  }
9093b4
+
9093b4
+  ~gdbpy_gil ()
9093b4
+  {
9093b4
+    PyGILState_Release (m_state);
9093b4
+  }
9093b4
+
9093b4
+  DISABLE_COPY_AND_ASSIGN (gdbpy_gil);
9093b4
+
9093b4
+private:
9093b4
+
9093b4
+  PyGILState_STATE m_state;
9093b4
+};
9093b4
+
9093b4
 /* Set the quit flag.  */
9093b4
 
9093b4
 static void
9093b4
@@ -247,6 +271,10 @@ gdbpy_set_quit_flag (const struct extension_language_defn *extlang)
9093b4
 static int
9093b4
 gdbpy_check_quit_flag (const struct extension_language_defn *extlang)
9093b4
 {
9093b4
+  if (!gdb_python_initialized)
9093b4
+    return 0;
9093b4
+
9093b4
+  gdbpy_gil gil;
9093b4
   return PyOS_InterruptOccurred ();
9093b4
 }
9093b4
 
9093b4
@@ -924,30 +952,6 @@ gdbpy_source_script (const struct extension_language_defn *extlang,
9093b4
 
9093b4
 /* Posting and handling events.  */
9093b4
 
9093b4
-/* A helper class to save and restore the GIL, but without touching
9093b4
-   the other globals that are handled by gdbpy_enter.  */
9093b4
-
9093b4
-class gdbpy_gil
9093b4
-{
9093b4
-public:
9093b4
-
9093b4
-  gdbpy_gil ()
9093b4
-    : m_state (PyGILState_Ensure ())
9093b4
-  {
9093b4
-  }
9093b4
-
9093b4
-  ~gdbpy_gil ()
9093b4
-  {
9093b4
-    PyGILState_Release (m_state);
9093b4
-  }
9093b4
-
9093b4
-  DISABLE_COPY_AND_ASSIGN (gdbpy_gil);
9093b4
-
9093b4
-private:
9093b4
-
9093b4
-  PyGILState_STATE m_state;
9093b4
-};
9093b4
-
9093b4
 /* A single event.  */
9093b4
 struct gdbpy_event
9093b4
 {
9093b4
@@ -1548,6 +1552,7 @@ finalize_python (void *ignore)
9093b4
 
9093b4
   Py_Finalize ();
9093b4
 
9093b4
+  gdb_python_initialized = false;
9093b4
   restore_active_ext_lang (previous_active);
9093b4
 }
9093b4
 
9093b4
@@ -1720,8 +1725,7 @@ do_start_initialization ()
9093b4
     return false;
9093b4
 
9093b4
   /* Release the GIL while gdb runs.  */
9093b4
-  PyThreadState_Swap (NULL);
9093b4
-  PyEval_ReleaseLock ();
9093b4
+  PyEval_SaveThread ();
9093b4
 
9093b4
   make_final_cleanup (finalize_python, NULL);
9093b4