diff --git a/_gdb.spec.Patch.include b/_gdb.spec.Patch.include index 1d8ffd9..917558b 100644 --- a/_gdb.spec.Patch.include +++ b/_gdb.spec.Patch.include @@ -400,3 +400,7 @@ Patch098: gdb-rhbz1818011-bfd-gcc10-error.patch # Backport fix for deprecation of PyEval_InitThreads in Python 3.9. Patch099: gdb-rhbz1822715-fix-python-deprecation.patch +# Backport "Fix Python 3.9 related runtime problems" +# Kevin Buettner and Keith Seitz +Patch100: gdb-rhbz1829702-fix-python39.patch + diff --git a/_gdb.spec.patch.include b/_gdb.spec.patch.include index dddd45a..fd3cf02 100644 --- a/_gdb.spec.patch.include +++ b/_gdb.spec.patch.include @@ -97,3 +97,4 @@ %patch097 -p1 %patch098 -p1 %patch099 -p1 +%patch100 -p1 diff --git a/_patch_order b/_patch_order index a4377d5..e56faa4 100644 --- a/_patch_order +++ b/_patch_order @@ -97,3 +97,4 @@ gdb-vla-intel-fix-print-char-array.patch gdb-rhbz1553104-s390x-arch12-test.patch gdb-rhbz1818011-bfd-gcc10-error.patch gdb-rhbz1822715-fix-python-deprecation.patch +gdb-rhbz1829702-fix-python39.patch diff --git a/gdb-rhbz1829702-fix-python39.patch b/gdb-rhbz1829702-fix-python39.patch new file mode 100644 index 0000000..d4eef56 --- /dev/null +++ b/gdb-rhbz1829702-fix-python39.patch @@ -0,0 +1,224 @@ +From FEDORA_PATCHES Mon Sep 17 00:00:00 2001 +From: Keith Seitz +Date: Thu, 4 Jun 2020 17:16:48 -0700 +Subject: gdb-rhbz1829702-fix-python39.patch + +;; Backport "Fix Python 3.9 related runtime problems" +;; Kevin Buettner and Keith Seitz + +commit c47bae859a5af0d95224d90000df0e529f7c5aa0 +Author: Kevin Buettner +Date: Wed May 27 20:05:40 2020 -0700 + + Fix Python3.9 related runtime problems + + Python3.9b1 is now available on Rawhide. GDB w/ Python 3.9 support + can be built using the configure switch -with-python=/usr/bin/python3.9. + + Attempting to run gdb/Python3.9 segfaults on startup: + + #0 0x00007ffff7b0582c in PyEval_ReleaseLock () from /lib64/libpython3.9 +.so.1.0 + #1 0x000000000069ccbf in do_start_initialization () + at worktree-test1/gdb/python/python.c:1789 + #2 _initialize_python () + at worktree-test1/gdb/python/python.c:1877 + #3 0x00000000007afb0a in initialize_all_files () at init.c:237 + ... + + Consulting the the documentation... + + https://docs.python.org/3/c-api/init.html + + ...we find that PyEval_ReleaseLock() has been deprecated since version + 3.2. It recommends using PyEval_SaveThread or PyEval_ReleaseThread() + instead. In do_start_initialization, in gdb/python/python.c, we + can replace the calls to PyThreadState_Swap() and PyEval_ReleaseLock() + with a single call to PyEval_SaveThread. (Thanks to Keith Seitz + for working this out.) + + With that in place, GDB gets a little bit further. It still dies + on startup, but the backtrace is different: + + #0 0x00007ffff7b04306 in PyOS_InterruptOccurred () + from /lib64/libpython3.9.so.1.0 + #1 0x0000000000576e86 in check_quit_flag () + at worktree-test1/gdb/extension.c:776 + #2 0x0000000000576f8a in set_active_ext_lang (now_active=now_active@entry=0x983c00 ) + at worktree-test1/gdb/extension.c:705 + #3 0x000000000069d399 in gdbpy_enter::gdbpy_enter (this=0x7fffffffd2d0, + gdbarch=0x0, language=0x0) + at worktree-test1/gdb/python/python.c:211 + #4 0x0000000000686e00 in python_new_inferior (inf=0xddeb10) + at worktree-test1/gdb/python/py-inferior.c:251 + #5 0x00000000005d9fb9 in std::function::operator()(inferior*) const (__args#0=, this=0xccad20) + at /usr/include/c++/10/bits/std_function.h:617 + #6 gdb::observers::observable::notify (args#0=0xddeb10, + this=) + at worktree-test1/gdb/../gdbsupport/observable.h:106 + #7 add_inferior_silent (pid=0) + at worktree-test1/gdb/inferior.c:113 + #8 0x00000000005dbcb8 in initialize_inferiors () + at worktree-test1/gdb/inferior.c:947 + ... + + We checked with some Python Developers and were told that we should + acquire the GIL prior to calling any Python C API function. We + definitely don't have the GIL for calls of PyOS_InterruptOccurred(). + + I moved class_gdbpy_gil earlier in the file and use it in + gdbpy_check_quit_flag() to acquire (and automatically release) the + GIL. + + With those changes in place, I was able to run to a GDB prompt. But, + when trying to quit, it segfaulted again due to due to some other + problems with gdbpy_check_quit_flag(): + + Thread 1 "gdb" received signal SIGSEGV, Segmentation fault. + 0x00007ffff7bbab0c in new_threadstate () from /lib64/libpython3.9.so.1.0 + (top-gdb) bt 8 + #0 0x00007ffff7bbab0c in new_threadstate () from /lib64/libpython3.9.so.1.0 + #1 0x00007ffff7afa5ea in PyGILState_Ensure.cold () + from /lib64/libpython3.9.so.1.0 + #2 0x000000000069b58c in gdbpy_gil::gdbpy_gil (this=) + at worktree-test1/gdb/python/python.c:278 + #3 gdbpy_check_quit_flag (extlang=) + at worktree-test1/gdb/python/python.c:278 + #4 0x0000000000576e96 in check_quit_flag () + at worktree-test1/gdb/extension.c:776 + #5 0x000000000057700c in restore_active_ext_lang (previous=0xe9c050) + at worktree-test1/gdb/extension.c:729 + #6 0x000000000088913a in do_my_cleanups ( + pmy_chain=0xc31870 , + old_chain=0xae5720 ) + at worktree-test1/gdbsupport/cleanups.cc:131 + #7 do_final_cleanups () + at worktree-test1/gdbsupport/cleanups.cc:143 + + In this case, we're trying to call a Python C API function after + Py_Finalize() has been called from finalize_python(). I made + finalize_python set gdb_python_initialized to false and then cause + check_quit_flag() to return early when it's false. + + With these changes in place, GDB seems to be working again with + Python3.9b1. I think it likely that there are other problems lurking. + I wouldn't be surprised to find that there are other calls into Python + where we don't first make sure that we have the GIL. Further changes + may well be needed. + + I see no regressions testing on Rawhide using a GDB built with the + default Python version (3.8.3) versus one built using Python 3.9b1. + + I've also tested on Fedora 28, 29, 30, 31, and 32 (all x86_64) using + the default (though updated) system installed versions of Python on + those OSes. This means that I've tested against Python versions + 2.7.15, 2.7.17, 2.7.18, 3.7.7, 3.8.2, and 3.8.3. In each case GDB + still builds without problem and shows no regressions after applying + this patch. + + gdb/ChangeLog: + + 2020-MM-DD Kevin Buettner + Keith Seitz + + * python/python.c (do_start_initialization): For Python 3.9 and + later, call PyEval_SaveThread instead of PyEval_ReleaseLock. + (class gdbpy_gil): Move to earlier in file. + (finalize_python): Set gdb_python_initialized. + (gdbpy_check_quit_flag): Acquire GIL via gdbpy_gil. Return early + when not initialized. + +diff --git a/gdb/python/python.c b/gdb/python/python.c +--- a/gdb/python/python.c ++++ b/gdb/python/python.c +@@ -234,6 +234,30 @@ gdbpy_enter::~gdbpy_enter () + PyGILState_Release (m_state); + } + ++/* A helper class to save and restore the GIL, but without touching ++ the other globals that are handled by gdbpy_enter. */ ++ ++class gdbpy_gil ++{ ++public: ++ ++ gdbpy_gil () ++ : m_state (PyGILState_Ensure ()) ++ { ++ } ++ ++ ~gdbpy_gil () ++ { ++ PyGILState_Release (m_state); ++ } ++ ++ DISABLE_COPY_AND_ASSIGN (gdbpy_gil); ++ ++private: ++ ++ PyGILState_STATE m_state; ++}; ++ + /* Set the quit flag. */ + + static void +@@ -247,6 +271,10 @@ gdbpy_set_quit_flag (const struct extension_language_defn *extlang) + static int + gdbpy_check_quit_flag (const struct extension_language_defn *extlang) + { ++ if (!gdb_python_initialized) ++ return 0; ++ ++ gdbpy_gil gil; + return PyOS_InterruptOccurred (); + } + +@@ -924,30 +952,6 @@ gdbpy_source_script (const struct extension_language_defn *extlang, + + /* Posting and handling events. */ + +-/* A helper class to save and restore the GIL, but without touching +- the other globals that are handled by gdbpy_enter. */ +- +-class gdbpy_gil +-{ +-public: +- +- gdbpy_gil () +- : m_state (PyGILState_Ensure ()) +- { +- } +- +- ~gdbpy_gil () +- { +- PyGILState_Release (m_state); +- } +- +- DISABLE_COPY_AND_ASSIGN (gdbpy_gil); +- +-private: +- +- PyGILState_STATE m_state; +-}; +- + /* A single event. */ + struct gdbpy_event + { +@@ -1548,6 +1552,7 @@ finalize_python (void *ignore) + + Py_Finalize (); + ++ gdb_python_initialized = false; + restore_active_ext_lang (previous_active); + } + +@@ -1720,8 +1725,7 @@ do_start_initialization () + return false; + + /* Release the GIL while gdb runs. */ +- PyThreadState_Swap (NULL); +- PyEval_ReleaseLock (); ++ PyEval_SaveThread (); + + make_final_cleanup (finalize_python, NULL); + diff --git a/gdb.spec b/gdb.spec index ace2c59..ec4f2c9 100644 --- a/gdb.spec +++ b/gdb.spec @@ -11,9 +11,6 @@ # workload gets run it decreases the general performance now. # --define 'scl somepkgname': Independent packages by scl-utils-build. -# https://bugzilla.redhat.com/show_bug.cgi?id=1829702 -%global _without_python 1 - %{?scl:%scl_package gdb} %{!?scl: %global pkg_name %{name} @@ -38,7 +35,7 @@ Version: 9.1 # The release always contains a leading reserved number, start it at 1. # `upstream' is not a part of `name' to stay fully rpm dependencies compatible for the testing. -Release: 7%{?dist} +Release: 8%{?dist} License: GPLv3+ and GPLv3+ with exceptions and GPLv2+ and GPLv2+ with exceptions and GPL+ and LGPLv2+ and LGPLv3+ and BSD and Public Domain and GFDL # Do not provide URL for snapshots as the file lasts there only for 2 days. @@ -1158,6 +1155,10 @@ fi %endif %changelog +* Fri Jun 5 2020 Keith Seitz - 9.1-8 +- Add patch for Python 3.9 and re-enable python. +- Update generate-*.sh to include stgit support. + * Thu May 21 2020 Miro HronĨok - 9.1-7 - Disable Python support to workaround problems with Python 3.9 (RHBZ 1829702) diff --git a/generate-git-repo-from-patches.sh b/generate-git-repo-from-patches.sh index 490cca9..012480d 100755 --- a/generate-git-repo-from-patches.sh +++ b/generate-git-repo-from-patches.sh @@ -14,7 +14,7 @@ usage () $0 -- Generate a git repository from .patch files Usage: - $0 + $0 [-u] [-h] is the directory where the rebase was performed. You need to clone the repository first. @@ -22,6 +22,7 @@ need to clone the repository first. Options are: -h: Print this message + -u: Uncommit all patches and initialize stgit repo EOF exit 0 } @@ -31,8 +32,21 @@ test -f gdb.spec || die "This script needs to run from the same directory as gdb test -z $1 && die "You need to specify the repository." test "$1" = "-h" && usage +uncommit=0 +if [ "$1" = "-u" ]; then + uncommit=1 + shift +fi + +git_repo=$1 +if [ ! -e $git_repo ]; then + echo "$0: repository \"$git_repo\" does not exist" + exit 1 +fi + test -f _git_upstream_commit || die "Cannot find _git_upstream_commit file." test -f _patch_order || die "Cannot find _patch_order file." +command -v stg > /dev/null 2>&1 || die "Cannot find stg. Is stgit installed?" last_ancestor_commit=`cat _git_upstream_commit` @@ -41,8 +55,19 @@ cd $1 git name-rev $last_ancestor_commit test $? -eq 0 || die "Could not find $last_ancestor_commit in the repository $1. Did you run 'git fetch'?" -git checkout $last_ancestor_commit +# Create a branch for the checkout; use the distro name in +# the name of this branch. +f=`cd .. && pwd` +name=devel-`basename $f` +git checkout -b $name $last_ancestor_commit +echo "Applying patches..." for p in `cat ../_patch_order` ; do git am ../$p test $? -eq 0 || die "Could not apply patch '$p'." done + +if (($uncommit)); then + echo "Uncommitting patches..." + stg init + stg uncommit -t $last_ancestor_commit -x +fi diff --git a/generate-patches-from-git-repo.sh b/generate-patches-from-git-repo.sh index f4b3326..c9bc3a9 100755 --- a/generate-patches-from-git-repo.sh +++ b/generate-patches-from-git-repo.sh @@ -52,6 +52,13 @@ done cd $1 +# If patches were uncommitted when the patches were applied, +# make sure that we're sitting at the top-most patch. Otherwise +# we'll only add patches up to the current top patch. +# It's safe to just assume stgit was used -- the push will simply +# fail. +stg push --all > /dev/null 2>&1 + git name-rev $commit_or_tag test $? -eq 0 || die "Could not find $commit_or_tag in the repository. Did you run 'git fetch'?"