]> granicus.if.org Git - python/commitdiff
Fixed multiple reinitialization of the Python interpreter. The small int list in...
authorChristian Heimes <christian@cheimes.de>
Thu, 31 Jan 2008 15:16:38 +0000 (15:16 +0000)
committerChristian Heimes <christian@cheimes.de>
Thu, 31 Jan 2008 15:16:38 +0000 (15:16 +0000)
Misc/NEWS
Objects/longobject.c

index 6b7b69296c25f7166a1c34d2cd25586c139fcbf5..a9da8b6ae211d20b033b7b7f1ad70a942bfebb58 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -12,6 +12,9 @@ What's New in Python 3.0a3?
 Core and Builtins
 -----------------
 
+- Fixed multiple reinitialization of the Python interpreter. The small int
+  list in longobject.c has caused a seg fault during the third finalization.
+
 - Issue #1973: bytes.fromhex('') raises SystemError
 
 - Issue #1771: remove cmp parameter from sorted() and list.sort()
index 18f158a78a467b6973f97c0e1572cec2c94d4ea5..fe9bf8e6e101ca003e747650286ad01be10f03ad 100644 (file)
@@ -3705,17 +3705,34 @@ int
 _PyLong_Init(void)
 {
 #if NSMALLNEGINTS + NSMALLPOSINTS > 0
-       int ival;
+       int ival, size;
        PyLongObject *v = small_ints;
-       for (ival = -NSMALLNEGINTS; ival < 0; ival++, v++) {
-               PyObject_INIT(v, &PyLong_Type);
-               Py_SIZE(v) = -1;
-               v->ob_digit[0] = -ival;
-       }
-       for (; ival < NSMALLPOSINTS; ival++, v++) {
-               PyObject_INIT(v, &PyLong_Type);
-               Py_SIZE(v) = ival ? 1 : 0;
-               v->ob_digit[0] = ival;
+
+       for (ival = -NSMALLNEGINTS; ival <  NSMALLPOSINTS; ival++, v++) {
+               size = (ival < 0) ? -1 : ((ival == 0) ? 0 : 1);
+               if (Py_TYPE(v) == &PyLong_Type) {
+                       /* The element is already initialized, most likely
+                        * the Python interpreter was initialized before.
+                        */
+                       /* _Py_NewReference((PyObject*)v);
+                        *  XXX: It sets the ref count to 1 but it may be
+                        * larger. Emulate new reference w/o setting refcnt
+                        * to 1.
+                        */
+                       PyObject* op = (PyObject*)v;
+                       _Py_INC_REFTOTAL;
+                       op->ob_refcnt = (op->ob_refcnt < 1) ? 1 : op->ob_refcnt;
+                       _Py_AddToAllObjects(op, 1);
+                       _Py_INC_TPALLOCS(op);
+
+                       assert(Py_SIZE(op) == size);
+                       assert(v->ob_digit[0] == abs(ival));
+               }
+               else {
+                       PyObject_INIT(v, &PyLong_Type);
+               }
+               Py_SIZE(v) = size;
+               v->ob_digit[0] = abs(ival);
        }
 #endif
        return 1;
@@ -3724,19 +3741,15 @@ _PyLong_Init(void)
 void
 PyLong_Fini(void)
 {
-#if 0
-       int i;
-       /* This is currently not needed; the small integers
-          are statically allocated */
+       /* Integers are currently statically allocated. Py_DECREF is not
+          needed, but Python must forget about the reference or multiple
+          reinitializations will fail. */
 #if NSMALLNEGINTS + NSMALLPOSINTS > 0
-        PyIntObject **q;
-
-        i = NSMALLNEGINTS + NSMALLPOSINTS;
-        q = small_ints;
-        while (--i >= 0) {
-                Py_XDECREF(*q);
-                *q++ = NULL;
-        }
-#endif
+       int i;
+       PyLongObject *v = small_ints;
+       for (i = 0; i < NSMALLNEGINTS + NSMALLPOSINTS; i++, v++) {
+               _Py_DEC_REFTOTAL;
+               _Py_ForgetReference((PyObject*)v);
+       }
 #endif
 }