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.
This commit is contained in:
parent
5bb3be2ffe
commit
9667ed23c5
|
@ -53,51 +53,58 @@ Exception\n\
|
|||
|\n\
|
||||
+-- 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\
|
||||
+-- KeyboardInterrupt\n\
|
||||
+-- ImportError\n\
|
||||
+-- EnvironmentError\n\
|
||||
| |\n\
|
||||
| +-- IOError\n\
|
||||
| +-- OSError\n\
|
||||
| |\n\
|
||||
| +-- WindowsError\n\
|
||||
+---Warning\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";
|
||||
+-- UserWarning\n\
|
||||
+-- DeprecationWarning\n\
|
||||
+-- SyntaxWarning\n\
|
||||
+-- RuntimeWarning";
|
||||
|
||||
|
||||
/* Helper function for populating a dictionary with method wrappers. */
|
||||
|
@ -168,6 +175,7 @@ make_class(PyObject **klass, PyObject *base,
|
|||
if (populate_methods(*klass, dict, methods)) {
|
||||
Py_DECREF(*klass);
|
||||
*klass = NULL;
|
||||
goto finally;
|
||||
}
|
||||
|
||||
status = 0;
|
||||
|
@ -1132,6 +1140,14 @@ fini_exceptions(void)
|
|||
PyExc_MemoryErrorInst = NULL;
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue