summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Misc/NEWS3
-rw-r--r--Objects/longobject.c59
2 files changed, 39 insertions, 23 deletions
diff --git a/Misc/NEWS b/Misc/NEWS
index 6b7b692..a9da8b6 100644
--- 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()
diff --git a/Objects/longobject.c b/Objects/longobject.c
index 18f158a..fe9bf8e 100644
--- a/Objects/longobject.c
+++ b/Objects/longobject.c
@@ -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
}