[Python-checkins] CVS: python/dist/src/Python exceptions.c,1.19,1.20
Barry Warsaw
bwarsaw@users.sourceforge.net
Tue, 23 Jan 2001 08:08:36 -0800
Update of /cvsroot/python/python/dist/src/Python
In directory usw-pr-cvs1:/tmp/cvs-serv3488
Modified Files:
exceptions.c
Log Message:
Leak pluggin', bug fixin' and better documentin'. Specifically,
module__doc__: Document the Warning subclass heirarchy.
make_class(): Added a "goto finally" so that if populate_methods()
fails, the return status will be -1 (failure) instead of 0 (success).
fini_exceptions(): When decref'ing the static pointers to the
exception classes, clear out their dictionaries too. This breaks a
cycle from class->dict->method->class and allows the classes with
unbound methods to be reclaimed. This plugs a large memory leak in a
common Py_Initialize()/dosomething/Py_Finalize() loop.
Index: exceptions.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/exceptions.c,v
retrieving revision 1.19
retrieving revision 1.20
diff -C2 -r1.19 -r1.20
*** exceptions.c 2000/12/15 21:58:29 1.19
--- exceptions.c 2001/01/23 16:08:34 1.20
***************
*** 27,31 ****
*/
static char
! module__doc__[] =
"Python's standard exception class hierarchy.\n\
\n\
--- 27,31 ----
*/
static char
! module__doc__[] =
"Python's standard exception class hierarchy.\n\
\n\
***************
*** 54,102 ****
+-- SystemExit\n\
+-- StandardError\n\
! |\n\
! +-- KeyboardInterrupt\n\
! +-- ImportError\n\
! +-- EnvironmentError\n\
! | |\n\
! | +-- IOError\n\
! | +-- OSError\n\
! | |\n\
! | +-- WindowsError\n\
! |\n\
! +-- EOFError\n\
! +-- RuntimeError\n\
! | |\n\
! | +-- NotImplementedError\n\
! |\n\
! +-- NameError\n\
! | |\n\
! | +-- UnboundLocalError\n\
! |\n\
! +-- AttributeError\n\
! +-- SyntaxError\n\
! | |\n\
! | +-- IndentationError\n\
! | |\n\
! | +-- TabError\n\
! |\n\
! +-- TypeError\n\
! +-- AssertionError\n\
! +-- LookupError\n\
! | |\n\
! | +-- IndexError\n\
! | +-- KeyError\n\
! |\n\
! +-- ArithmeticError\n\
! | |\n\
! | +-- OverflowError\n\
! | +-- ZeroDivisionError\n\
! | +-- FloatingPointError\n\
! |\n\
! +-- ValueError\n\
! | |\n\
! | +-- UnicodeError\n\
|\n\
! +-- SystemError\n\
! +-- MemoryError";
--- 54,109 ----
+-- SystemExit\n\
+-- StandardError\n\
! | |\n\
! | +-- KeyboardInterrupt\n\
! | +-- ImportError\n\
! | +-- EnvironmentError\n\
! | | |\n\
! | | +-- IOError\n\
! | | +-- OSError\n\
! | | |\n\
! | | +-- WindowsError\n\
! | |\n\
! | +-- EOFError\n\
! | +-- RuntimeError\n\
! | | |\n\
! | | +-- NotImplementedError\n\
! | |\n\
! | +-- NameError\n\
! | | |\n\
! | | +-- UnboundLocalError\n\
! | |\n\
! | +-- AttributeError\n\
! | +-- SyntaxError\n\
! | | |\n\
! | | +-- IndentationError\n\
! | | |\n\
! | | +-- TabError\n\
! | |\n\
! | +-- TypeError\n\
! | +-- AssertionError\n\
! | +-- LookupError\n\
! | | |\n\
! | | +-- IndexError\n\
! | | +-- KeyError\n\
! | |\n\
! | +-- ArithmeticError\n\
! | | |\n\
! | | +-- OverflowError\n\
! | | +-- ZeroDivisionError\n\
! | | +-- FloatingPointError\n\
! | |\n\
! | +-- ValueError\n\
! | | |\n\
! | | +-- UnicodeError\n\
! | |\n\
! | +-- SystemError\n\
! | +-- MemoryError\n\
! |\n\
! +---Warning\n\
|\n\
! +-- UserWarning\n\
! +-- DeprecationWarning\n\
! +-- SyntaxWarning\n\
! +-- RuntimeWarning";
***************
*** 122,126 ****
return -1;
}
!
/* add method to dictionary */
status = PyDict_SetItemString(dict, methods->ml_name, meth);
--- 129,133 ----
return -1;
}
!
/* add method to dictionary */
status = PyDict_SetItemString(dict, methods->ml_name, meth);
***************
*** 137,141 ****
}
!
/* This function is used to create all subsequent exception classes. */
--- 144,148 ----
}
!
/* This function is used to create all subsequent exception classes. */
***************
*** 169,172 ****
--- 176,180 ----
Py_DECREF(*klass);
*klass = NULL;
+ goto finally;
}
***************
*** 334,338 ****
if (!(name = PyString_FromString("Exception")))
goto finally;
!
if (!(PyExc_Exception = PyClass_New(NULL, dict, name)))
goto finally;
--- 342,346 ----
if (!(name = PyString_FromString("Exception")))
goto finally;
!
if (!(PyExc_Exception = PyClass_New(NULL, dict, name)))
goto finally;
***************
*** 380,384 ****
if (!(args = PySequence_GetSlice(args, 1, PySequence_Size(args))))
return NULL;
!
status = PyObject_SetAttrString(self, "args", args);
if (status < 0) {
--- 388,392 ----
if (!(args = PySequence_GetSlice(args, 1, PySequence_Size(args))))
return NULL;
!
status = PyObject_SetAttrString(self, "args", args);
if (status < 0) {
***************
*** 462,468 ****
* called, giving a third argument which is the filename. But, so
* that old code using in-place unpacking doesn't break, e.g.:
! *
* except IOError, (errno, strerror):
! *
* we hack args so that it only contains two items. This also
* means we need our own __str__() which prints out the filename
--- 470,476 ----
* called, giving a third argument which is the filename. But, so
* that old code using in-place unpacking doesn't break, e.g.:
! *
* except IOError, (errno, strerror):
! *
* we hack args so that it only contains two items. This also
* means we need our own __str__() which prints out the filename
***************
*** 474,478 ****
if (!item0 || !item1 || !item2)
goto finally;
!
if (PyObject_SetAttrString(self, "errno", item0) ||
PyObject_SetAttrString(self, "strerror", item1) ||
--- 482,486 ----
if (!item0 || !item1 || !item2)
goto finally;
!
if (PyObject_SetAttrString(self, "errno", item0) ||
PyObject_SetAttrString(self, "strerror", item1) ||
***************
*** 495,499 ****
if (!item0 || !item1)
goto finally;
!
if (PyObject_SetAttrString(self, "errno", item0) ||
PyObject_SetAttrString(self, "strerror", item1))
--- 503,507 ----
if (!item0 || !item1)
goto finally;
!
if (PyObject_SetAttrString(self, "errno", item0) ||
PyObject_SetAttrString(self, "strerror", item1))
***************
*** 528,532 ****
if (!PyArg_ParseTuple(args, "O:__str__", &self))
return NULL;
!
filename = PyObject_GetAttrString(self, "filename");
serrno = PyObject_GetAttrString(self, "errno");
--- 536,540 ----
if (!PyArg_ParseTuple(args, "O:__str__", &self))
return NULL;
!
filename = PyObject_GetAttrString(self, "filename");
serrno = PyObject_GetAttrString(self, "errno");
***************
*** 571,575 ****
PyTuple_SET_ITEM(tuple, 0, serrno);
PyTuple_SET_ITEM(tuple, 1, strerror);
!
rtnval = PyString_Format(fmt, tuple);
--- 579,583 ----
PyTuple_SET_ITEM(tuple, 0, serrno);
PyTuple_SET_ITEM(tuple, 1, strerror);
!
rtnval = PyString_Format(fmt, tuple);
***************
*** 1064,1068 ****
Py_FatalError("Base class `Exception' could not be created.");
}
!
/* Now we can programmatically create all the remaining exceptions.
* Remember to start the loop at 1 to skip Exceptions.
--- 1072,1076 ----
Py_FatalError("Base class `Exception' could not be created.");
}
!
/* Now we can programmatically create all the remaining exceptions.
* Remember to start the loop at 1 to skip Exceptions.
***************
*** 1133,1136 ****
--- 1141,1152 ----
for (i=0; exctable[i].name; i++) {
+ /* clear the class's dictionary, freeing up circular references
+ * between the class and its methods.
+ */
+ PyObject* cdict = PyObject_GetAttrString(*exctable[i].exc, "__dict__");
+ PyDict_Clear(cdict);
+ Py_DECREF(cdict);
+
+ /* Now decref the exception class */
Py_XDECREF(*exctable[i].exc);
*exctable[i].exc = NULL;