summaryrefslogtreecommitdiffstats
path: root/Python
diff options
context:
space:
mode:
authorBarry Warsaw <barry@python.org>1998-09-14 18:51:11 (GMT)
committerBarry Warsaw <barry@python.org>1998-09-14 18:51:11 (GMT)
commit98b6246c0c60f2831b0c7a66d8c0659ebac1ec32 (patch)
tree791103c11cac7411bbe9a370a10e4c30d84196a8 /Python
parentd24d3fcd03d2396eb5cc7524246183b661c4113e (diff)
downloadcpython-98b6246c0c60f2831b0c7a66d8c0659ebac1ec32.zip
cpython-98b6246c0c60f2831b0c7a66d8c0659ebac1ec32.tar.gz
cpython-98b6246c0c60f2831b0c7a66d8c0659ebac1ec32.tar.bz2
Several changes that Python carry on in the face of errors in the
initialization of class exceptions. Specifically: init_class_exc(): This function now returns an integer status of the class exception initialization. No fatal errors in this method now. Also, use PySys_WriteStderr() when writing error messages. When an error occurs in this function, 0 is returned, but the partial creation of the exception classes is not undone (this happens elsewhere). Things that could trigger the fallback: - exceptions.py fails to be imported (due to syntax error, etc.) - one of the exception classes is missing (e.g. due to library version mismatch) - exception class can't be inserted into __builtin__'s dictionary - MemoryError instance can't be pre-allocated - some other PyErr_Occurred newstdexception(): Changed the error message. This is still a fatal error because if the string based exceptions can't be created, we really can't continue. initerrors(): Be sure to xdecref the .exc field, which might be non-NULL if class exceptions init was aborted. _PyBuiltin_Init_2(): If class exception init fails, print a warning message and reinstate the string based exceptions.
Diffstat (limited to 'Python')
-rw-r--r--Python/bltinmodule.c87
1 files changed, 61 insertions, 26 deletions
diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c
index 86e455f..4f91397 100644
--- a/Python/bltinmodule.c
+++ b/Python/bltinmodule.c
@@ -1987,40 +1987,43 @@ bltin_exc[] = {
};
-/* import exceptions module to extract class exceptions */
-static void
+/* import exceptions module to extract class exceptions. on success,
+ * return 1. on failure return 0 which signals _PyBuiltin_Init_2 to fall
+ * back to using old-style string based exceptions.
+ */
+static int
init_class_exc(dict)
PyObject *dict;
{
int i;
PyObject *m = PyImport_ImportModule("exceptions");
- PyObject *d;
- PyObject *args;
+ PyObject *args = NULL;
+ PyObject *d = NULL;
+ /* make sure we got the module and its dictionary */
if (m == NULL ||
(d = PyModule_GetDict(m)) == NULL)
{
- /* XXX Should use PySys_WriteStderr here */
- PyObject *f = PySys_GetObject("stderr");
+ PySys_WriteStderr("'import exceptions' failed; ");
if (Py_VerboseFlag) {
- PyFile_WriteString(
- "'import exceptions' failed; traceback:\n", f);
+ PySys_WriteStderr("traceback:\n");
PyErr_Print();
}
else {
- PyFile_WriteString(
- "'import exceptions' failed; use -v for traceback\n", f);
- PyErr_Clear();
+ PySys_WriteStderr("use -v for traceback\n");
}
- PyFile_WriteString("defaulting to old style exceptions\n", f);
- return;
+ goto finally;
}
for (i = 0; bltin_exc[i].name; i++) {
/* dig the exception out of the module */
PyObject *exc = PyDict_GetItemString(d, bltin_exc[i].name);
- if (!exc)
- Py_FatalError("built-in exception cannot be initialized");
-
+ if (!exc) {
+ PySys_WriteStderr(
+ "Built-in exception class not found: %s. Library mismatch?\n",
+ bltin_exc[i].name);
+ goto finally;
+ }
+ /* free the old-style exception string object */
Py_XDECREF(*bltin_exc[i].exc);
/* squirrel away a pointer to the exception */
@@ -2028,22 +2031,44 @@ init_class_exc(dict)
*bltin_exc[i].exc = exc;
/* and insert the name in the __builtin__ module */
- PyDict_SetItemString(dict, bltin_exc[i].name, exc);
+ if (PyDict_SetItemString(dict, bltin_exc[i].name, exc)) {
+ PySys_WriteStderr(
+ "Cannot insert exception into __builtin__: %s\n",
+ bltin_exc[i].name);
+ goto finally;
+ }
}
/* we need one pre-allocated instance */
args = Py_BuildValue("()");
- if (args) {
- PyExc_MemoryErrorInst =
- PyEval_CallObject(PyExc_MemoryError, args);
- Py_DECREF(args);
+ if (!args ||
+ !(PyExc_MemoryErrorInst =
+ PyEval_CallObject(PyExc_MemoryError, args)))
+ {
+ PySys_WriteStderr("Cannot pre-allocate MemoryError instance\n");
+ goto finally;
}
+ Py_DECREF(args);
/* we're done with the exceptions module */
Py_DECREF(m);
- if (PyErr_Occurred())
- Py_FatalError("can't instantiate standard exceptions");
+ if (PyErr_Occurred()) {
+ PySys_WriteStderr("Cannot initialize standard class exceptions; ");
+ if (Py_VerboseFlag) {
+ PySys_WriteStderr("traceback:\n");
+ PyErr_Print();
+ }
+ else
+ PySys_WriteStderr("use -v for traceback\n");
+ goto finally;
+ }
+ return 1;
+ finally:
+ Py_XDECREF(m);
+ Py_XDECREF(args);
+ PyErr_Clear();
+ return 0;
}
@@ -2062,7 +2087,7 @@ newstdexception(dict, name)
{
PyObject *v = PyString_FromString(name);
if (v == NULL || PyDict_SetItemString(dict, name, v) != 0)
- Py_FatalError("no mem for new standard exception");
+ Py_FatalError("Cannot create string-based exceptions");
return v;
}
@@ -2073,6 +2098,7 @@ initerrors(dict)
int i;
int exccnt = 0;
for (i = 0; bltin_exc[i].name; i++, exccnt++) {
+ Py_XDECREF(*bltin_exc[i].exc);
if (bltin_exc[i].leaf_exc)
*bltin_exc[i].exc =
newstdexception(dict, bltin_exc[i].name);
@@ -2166,8 +2192,17 @@ _PyBuiltin_Init_2(dict)
PyObject *dict;
{
/* if Python was started with -X, initialize the class exceptions */
- if (Py_UseClassExceptionsFlag)
- init_class_exc(dict);
+ if (Py_UseClassExceptionsFlag) {
+ if (!init_class_exc(dict)) {
+ /* class based exceptions could not be
+ * initialized. Fall back to using string based
+ * exceptions.
+ */
+ PySys_WriteStderr(
+ "Warning! Falling back to string-based exceptions\n");
+ initerrors(dict);
+ }
+ }
}