[Zope-dev] ding, dong, the segfault is dead. Patch attached

Leonardo Rochael Almeida leo@hiper.com.br
02 Apr 2002 14:20:29 -0300


This is a MIME-formatted message.  If you see this text it means that your
E-mail software does not support MIME-formatted messages.

--=_spitfire-27584-1017768030-0001-2
Content-Type: text/plain; charset=iso-8859-1
Content-Transfer-Encoding: 7bit

On Mon, 2002-04-01 at 19:57, Leonardo Rochael Almeida wrote:
> On Thu, 2002-03-28 at 15:33, Matthew T. Kromer wrote:
> > [...]
> > The relevant report at sourceforge is:
> >     
> > http://sourceforge.net/tracker/?func=detail&atid=105470&aid=535905&group_id=5470
> [...]
> Which is (or where can I find) the currently official patchset to apply
> against Python-2.1.2 source?

When you want something done right you just go and do it yourself,
right?

Attached is a patch for the Python source that was taken from a diff of
the 2.1 maintenance branch against the original 2.1.2 release, cleaned
up so that it only contains modifications that are relevant to the crash
problems.

To make it your self you should get a Python cvs sandbox (instructions
here http://sourceforge.net/cvs/?group_id=5470 the CVS module is python)
get into the python/dist/src directory and run this command:

cvs -z3 -d:pserver:anonymous@cvs.python.sourceforge.net:/cvsroot/python
diff -u -kk -r r212 -r release21-maint Modules/gcmodule.c Objects Python
> ../../../segfault-fix.diff

(If my MUA wrapped it, it's all in one line, obviously)

I just put this patch up in production environment and it's been up for
more than 1h30m now, which for me is enough indication that it's in fact
the final solution to the problem.

Cheers.

-- 
Ideas don't stay in some minds very long because they don't like
solitary confinement.


--=_spitfire-27584-1017768030-0001-2
Content-Type: text/x-patch; charset=iso-8859-1
Content-Transfer-Encoding: quoted-printable
Content-Description: Patch against Python 2.1.2
Content-Disposition: inline; filename=segfault-fix.diff

Index: Modules/gcmodule.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvsroot/python/python/dist/src/Modules/gcmodule.c,v
retrieving revision 2.15.6.1
retrieving revision 2.15.6.2
diff -u -r2.15.6.1 -r2.15.6.2
--- Modules/gcmodule.c	1 Nov 2001 15:34:20 -0000	2.15.6.1
+++ Modules/gcmodule.c	28 Mar 2002 20:41:02 -0000	2.15.6.2
@@ -87,12 +87,14 @@
 static void
 gc_list_remove(PyGC_Head *node)
 {
+	if (node->gc_next =3D=3D NULL)
+		return;
 	node->gc_prev->gc_next =3D node->gc_next;
 	node->gc_next->gc_prev =3D node->gc_prev;
 #ifdef Py_DEBUG
 	node->gc_prev =3D NULL;
-	node->gc_next =3D NULL;
 #endif
+	node->gc_next =3D NULL;
 }
=20
 static void=20
Index: Objects/dictobject.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvsroot/python/python/dist/src/Objects/dictobject.c,v
retrieving revision 2.76.2.1
retrieving revision 2.76.2.2
diff -u -r2.76.2.1 -r2.76.2.2
--- Objects/dictobject.c	23 May 2001 15:07:55 -0000	2.76.2.1
+++ Objects/dictobject.c	28 Mar 2002 20:41:02 -0000	2.76.2.2
@@ -619,8 +619,8 @@
 {
 	register int i;
 	register dictentry *ep;
-	Py_TRASHCAN_SAFE_BEGIN(mp)
 	PyObject_GC_Fini(mp);
+	Py_TRASHCAN_SAFE_BEGIN(mp)
 	for (i =3D 0, ep =3D mp->ma_table; i < mp->ma_size; i++, ep++) {
 		if (ep->me_key !=3D NULL) {
 			Py_DECREF(ep->me_key);
Index: Objects/listobject.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvsroot/python/python/dist/src/Objects/listobject.c,v
retrieving revision 2.92.4.1
retrieving revision 2.92.4.2
diff -u -r2.92.4.1 -r2.92.4.2
--- Objects/listobject.c	6 Jul 2001 17:48:47 -0000	2.92.4.1
+++ Objects/listobject.c	28 Mar 2002 20:41:02 -0000	2.92.4.2
@@ -176,8 +176,8 @@
 list_dealloc(PyListObject *op)
 {
 	int i;
-	Py_TRASHCAN_SAFE_BEGIN(op)
 	PyObject_GC_Fini(op);
+	Py_TRASHCAN_SAFE_BEGIN(op)
 	if (op->ob_item !=3D NULL) {
 		/* Do it backwards, for Christian Tismer.
 		   There's a simple test case where somehow this reduces
Index: Objects/tupleobject.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvsroot/python/python/dist/src/Objects/tupleobject.c,v
retrieving revision 2.48.4.3
retrieving revision 2.48.4.4
diff -u -r2.48.4.3 -r2.48.4.4
--- Objects/tupleobject.c	6 Jul 2001 17:48:47 -0000	2.48.4.3
+++ Objects/tupleobject.c	28 Mar 2002 20:41:02 -0000	2.48.4.4
@@ -143,8 +143,8 @@
 {
 	register int i;
 	register int len =3D  op->ob_size;
-	Py_TRASHCAN_SAFE_BEGIN(op)
 	PyObject_GC_Fini(op);
+	Py_TRASHCAN_SAFE_BEGIN(op)
 	if (len > 0) {
 		i =3D len;
 		while (--i >=3D 0)
Index: Python/ceval.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvsroot/python/python/dist/src/Python/ceval.c,v
retrieving revision 2.238.2.5
retrieving revision 2.238.2.6
diff -u -r2.238.2.5 -r2.238.2.6
--- Python/ceval.c	20 Dec 2001 02:07:36 -0000	2.238.2.5
+++ Python/ceval.c	28 Mar 2002 20:21:21 -0000	2.238.2.6
@@ -414,8 +414,16 @@
 /* Local variable macros */
=20
 #define GETLOCAL(i)	(fastlocals[i])
-#define SETLOCAL(i, value)	do { Py_XDECREF(GETLOCAL(i)); \
-				     GETLOCAL(i) =3D value; } while (0)
+
+/* The SETLOCAL() macro must not DECREF the local variable in-place and
+   then store the new value; it must copy the old value to a temporary
+   value, then store the new value, and then DECREF the temporary value.
+   This is because it is possible that during the DECREF the frame is
+   accessed by other code (e.g. a __del__ method or gc.collect()) and the
+   variable would be pointing to already-freed memory. */
+#define SETLOCAL(i, value)	do { PyObject *tmp =3D GETLOCAL(i); \
+				     GETLOCAL(i) =3D value; \
+                                     Py_XDECREF(tmp); } while (0)
=20
 /* Start of code */
=20

--=_spitfire-27584-1017768030-0001-2--