[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;