diff options
author | Barry Warsaw <barry@python.org> | 1998-09-14 18:51:11 (GMT) |
---|---|---|
committer | Barry Warsaw <barry@python.org> | 1998-09-14 18:51:11 (GMT) |
commit | 98b6246c0c60f2831b0c7a66d8c0659ebac1ec32 (patch) | |
tree | 791103c11cac7411bbe9a370a10e4c30d84196a8 /Python/bltinmodule.c | |
parent | d24d3fcd03d2396eb5cc7524246183b661c4113e (diff) | |
download | cpython-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/bltinmodule.c')
-rw-r--r-- | Python/bltinmodule.c | 87 |
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); + } + } } |