[Python-checkins] r69658 - in python/branches/io-c/Modules: _bufferedio.c _iobase.c _textio.c
antoine.pitrou
python-checkins at python.org
Mon Feb 16 02:38:59 CET 2009
Author: antoine.pitrou
Date: Mon Feb 16 02:38:59 2009
New Revision: 69658
Log:
Fix crash in test_urllib2_localnet in debug mode. It was due to an HTTPResponse
object being revived when calling its close() method in IOBase's tp_dealloc.
_PyIOBase_finalize() starts looking scary...
Modified:
python/branches/io-c/Modules/_bufferedio.c
python/branches/io-c/Modules/_iobase.c
python/branches/io-c/Modules/_textio.c
Modified: python/branches/io-c/Modules/_bufferedio.c
==============================================================================
--- python/branches/io-c/Modules/_bufferedio.c (original)
+++ python/branches/io-c/Modules/_bufferedio.c Mon Feb 16 02:38:59 2009
@@ -296,6 +296,7 @@
{
if (self->ok && _PyIOBase_finalize((PyObject *) self) < 0)
return;
+ _PyObject_GC_UNTRACK(self);
self->ok = 0;
if (self->weakreflist != NULL)
PyObject_ClearWeakRefs((PyObject *)self);
Modified: python/branches/io-c/Modules/_iobase.c
==============================================================================
--- python/branches/io-c/Modules/_iobase.c (original)
+++ python/branches/io-c/Modules/_iobase.c Mon Feb 16 02:38:59 2009
@@ -186,20 +186,22 @@
Py_RETURN_NONE;
}
-/* Destructor */
-
int
_PyIOBase_finalize(PyObject *self)
{
PyObject *res;
PyObject *tp, *v, *tb;
- PyObject **dictptr;
int closed = 1;
+ int is_zombie;
+
PyErr_Fetch(&tp, &v, &tb);
- /* We need to resurrect the object as calling close() can invoke
- arbitrary code. */
- Py_REFCNT(self)++;
- /* The object could already be in an usable state, so we'll take any
+ /* If _PyIOBase_finalize() is called from a destructor, we need to
+ resurrect the object as calling close() can invoke arbitrary code. */
+ is_zombie = (Py_REFCNT(self) == 0);
+ if (is_zombie) {
+ ++Py_REFCNT(self);
+ }
+ /* The object could already be in an unusable state, so we'll take any
error as meaning "stop, nothing to see here". */
/* XXX any Python method or property called from here may rely on
attributes being set in the instance __dict__, but the __dict__ has
@@ -222,22 +224,52 @@
else
Py_DECREF(res);
}
- /* The code above might have re-added a dict, DECREF it */
- dictptr = _PyObject_GetDictPtr(self);
- if (dictptr != NULL)
- Py_CLEAR(*dictptr);
PyErr_Restore(tp, v, tb);
- if (--Py_REFCNT(self) != 0) {
- return -1;
+ if (is_zombie) {
+ if (--Py_REFCNT(self) != 0) {
+ /* The object lives again. The following code is taken from
+ slot_tp_del in typeobject.c. */
+ Py_ssize_t refcnt = Py_REFCNT(self);
+ _Py_NewReference(self);
+ Py_REFCNT(self) = refcnt;
+ /* If Py_REF_DEBUG, _Py_NewReference bumped _Py_RefTotal, so
+ * we need to undo that. */
+ _Py_DEC_REFTOTAL;
+ /* If Py_TRACE_REFS, _Py_NewReference re-added self to the object
+ * chain, so no more to do there.
+ * If COUNT_ALLOCS, the original decref bumped tp_frees, and
+ * _Py_NewReference bumped tp_allocs: both of those need to be
+ * undone.
+ */
+#ifdef COUNT_ALLOCS
+ --Py_TYPE(self)->tp_frees;
+ --Py_TYPE(self)->tp_allocs;
+#endif
+ return -1;
+ }
+ else {
+ /* The code above might have re-added a dict, DECREF it */
+ PyObject **dictptr = _PyObject_GetDictPtr(self);
+ if (dictptr != NULL)
+ Py_CLEAR(*dictptr);
+ }
}
return 0;
}
+/* Destructor */
+
static void
IOBase_dealloc(PyObject *self)
{
- if (_PyIOBase_finalize(self) == 0)
- Py_TYPE(self)->tp_free(self);
+ if (_PyIOBase_finalize((PyObject *)self) < 0) {
+ /* When called from a heap type's dealloc, the type will be
+ decref'ed on return (see e.g. subtype_dealloc in typeobject.c). */
+ if (PyType_HasFeature(Py_TYPE(self), Py_TPFLAGS_HEAPTYPE))
+ Py_INCREF(Py_TYPE(self));
+ return;
+ }
+ Py_TYPE(self)->tp_free(self);
}
/* Inquiry methods */
@@ -683,7 +715,6 @@
PyType_GenericNew, /* tp_new */
};
-
/*
* RawIOBase class, Inherits from IOBase.
Modified: python/branches/io-c/Modules/_textio.c
==============================================================================
--- python/branches/io-c/Modules/_textio.c (original)
+++ python/branches/io-c/Modules/_textio.c Mon Feb 16 02:38:59 2009
@@ -943,6 +943,7 @@
{
if (_TextIOWrapper_clear(self) < 0)
return;
+ _PyObject_GC_UNTRACK(self);
if (self->weakreflist != NULL)
PyObject_ClearWeakRefs((PyObject *)self);
Py_CLEAR(self->dict);
More information about the Python-checkins
mailing list