From bafa5fa3af4b36ea6208475df19738f4fc1ad12f Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Jun 06 2011 15:39:54 +0000 Subject: add upstream patch to solve Python GC crash during gobject deallocation Acked by J5 on IRC --- diff --git a/PyGObject-deallocation-GC-crash.patch b/PyGObject-deallocation-GC-crash.patch new file mode 100644 index 0000000..800694b --- /dev/null +++ b/PyGObject-deallocation-GC-crash.patch @@ -0,0 +1,87 @@ +From 92aca4416a7930e5870b8d1a4016bae8140462ee Mon Sep 17 00:00:00 2001 +From: Daniel Drake +Date: Fri, 3 Jun 2011 16:59:15 +0100 +Subject: [PATCH] Fix GC-related crash during PyGObject deallocation + +Python-2.7.1's GC source has the following comment: + + /* Python's cyclic gc should never see an incoming refcount + * of 0: if something decref'ed to 0, it should have been + * deallocated immediately at that time. + * Possible cause (if the assert triggers): a tp_dealloc + * routine left a gc-aware object tracked during its teardown + * phase, and did something-- or allowed something to happen -- + * that called back into Python. gc can trigger then, and may + * see the still-tracked dying object. Before this assert + * was added, such mistakes went on to allow gc to try to + * delete the object again. In a debug build, that caused + * a mysterious segfault, when _Py_ForgetReference tried + * to remove the object from the doubly-linked list of all + * objects a second time. In a release build, an actual + * double deallocation occurred, which leads to corruption + * of the allocator's internal bookkeeping pointers. That's + * so serious that maybe this should be a release-build + * check instead of an assert? + */ + +As shown in a backtrace at +https://bugzilla.redhat.com/show_bug.cgi?id=640972 , pygobject is making +this exact mistake. Before untracking its object, pygobject_dealloc +calls PyObject_ClearWeakRefs() which can call back into python, create +new allocations, and trigger the GC. + +This is causing Sugar (based on pygobject2 + pygtk2 static bindings) to +crash on a regular basis while interacting with widgets or launching +applications. + +Fix this by untracking the object early. Also fix the same issue spotted +in the GSource wrapper. + +Thanks to Bernie Innocenti for initial diagnosis. +--- + glib/pygsource.c | 6 ++++-- + gobject/pygobject.c | 8 +++++++- + 2 files changed, 11 insertions(+), 3 deletions(-) + +diff --git a/glib/pygsource.c b/glib/pygsource.c +index 684711e..d0176ab 100644 +--- a/glib/pygsource.c ++++ b/glib/pygsource.c +@@ -387,10 +387,12 @@ pyg_source_clear(PyGSource *self) + static void + pyg_source_dealloc(PyGSource *self) + { +- PyObject_ClearWeakRefs((PyObject *)self); +- ++ /* Must be done first, so that there is no chance of Python's GC being ++ * called while tracking this half-deallocated object */ + PyObject_GC_UnTrack((PyObject *)self); + ++ PyObject_ClearWeakRefs((PyObject *)self); ++ + pyg_source_clear(self); + + PyObject_GC_Del(self); +diff --git a/gobject/pygobject.c b/gobject/pygobject.c +index 0faf221..3193890 100644 +--- a/gobject/pygobject.c ++++ b/gobject/pygobject.c +@@ -1028,8 +1028,14 @@ PYGLIB_DEFINE_TYPE("gobject.GObject", PyGObject_Type, PyGObject); + static void + pygobject_dealloc(PyGObject *self) + { +- PyObject_ClearWeakRefs((PyObject *)self); ++ /* Untrack must be done first. This is because followup calls such as ++ * ClearWeakRefs could call into Python and cause new allocations to ++ * happen, which could in turn could trigger the garbage collector, ++ * which would then get confused as it is tracking this half-deallocated ++ * object. */ + PyObject_GC_UnTrack((PyObject *)self); ++ ++ PyObject_ClearWeakRefs((PyObject *)self); + /* this forces inst_data->type to be updated, which could prove + * important if a new wrapper has to be created and it is of a + * unregistered type */ +-- +1.7.5.2 + diff --git a/pygobject2.spec b/pygobject2.spec index 4f17bc7..145ffe3 100644 --- a/pygobject2.spec +++ b/pygobject2.spec @@ -12,7 +12,7 @@ Name: pygobject2 Version: 2.28.4 -Release: 2%{?dist} +Release: 3%{?dist} License: LGPLv2+ Group: Development/Languages Summary: Python 2 bindings for GObject @@ -21,6 +21,11 @@ BuildRoot: %{_tmppath}/%{name}-%{version}-root #VCS: git:git://git.gnome.org/pygobject Source: http://ftp.gnome.org/pub/GNOME/sources/pygobject/2.28/pygobject-%{version}.tar.bz2 +### Patches ### + +# fixes Sugar crashes, already upstream +Patch0: PyGObject-deallocation-GC-crash.patch + ### Build Dependencies ### BuildRequires: glib2-devel >= %{glib2_version} @@ -90,6 +95,7 @@ for use in Python 3 programs. %prep %setup -q -n pygobject-%{version} +%patch0 -p1 -b .dealloc-gc %if 0%{?with_python3} rm -rf %{py3dir} @@ -191,6 +197,9 @@ rm examples/Makefile* %endif # with_python3 %changelog +* Mon Jun 06 2011 Daniel Drake - 2.28.4-3 +- add upstream patch to solve Python GC crash during gobject deallocation + * Thu Apr 21 2011 John (J5) Palmieri - 2.28.4-2 - require gobject-introspection version 0.10.8