summaryrefslogtreecommitdiff
path: root/Objects/exceptions.c
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@redhat.com>2019-01-22 17:39:03 +0100
committerGitHub <noreply@github.com>2019-01-22 17:39:03 +0100
commitbf4ac2d2fd520c61306b2676db488adab9b5d8c5 (patch)
tree36b7680e9ac88256ba0f3beeb834c677a20914f8 /Objects/exceptions.c
parent35ca1820e19f81f69073f294503cdcd708fe490f (diff)
downloadcpython-git-bf4ac2d2fd520c61306b2676db488adab9b5d8c5.tar.gz
bpo-35713: Rework Python initialization (GH-11647)
* The PyByteArray_Init() and PyByteArray_Fini() functions have been removed. They did nothing since Python 2.7.4 and Python 3.2.0, were excluded from the limited API (stable ABI), and were not documented. * Move "_PyXXX_Init()" and "_PyXXX_Fini()" declarations from Include/cpython/pylifecycle.h to Include/internal/pycore_pylifecycle.h. Replace "PyAPI_FUNC(TYPE)" with "extern TYPE". * _PyExc_Init() now returns an error on failure rather than calling Py_FatalError(). Move macros inside _PyExc_Init() and undefine them when done. Rewrite macros to make them look more like statement: add ";" when using them, add "do { ... } while (0)". * _PyUnicode_Init() now returns a _PyInitError error rather than call Py_FatalError(). * Move stdin check from _PySys_BeginInit() to init_sys_streams(). * _Py_ReadyTypes() now returns a _PyInitError error rather than calling Py_FatalError().
Diffstat (limited to 'Objects/exceptions.c')
-rw-r--r--Objects/exceptions.c395
1 files changed, 207 insertions, 188 deletions
diff --git a/Objects/exceptions.c b/Objects/exceptions.c
index 002a602373..8d81566c7f 100644
--- a/Objects/exceptions.c
+++ b/Objects/exceptions.c
@@ -2299,7 +2299,7 @@ MemoryError_dealloc(PyBaseExceptionObject *self)
}
}
-static void
+static int
preallocate_memerrors(void)
{
/* We create enough MemoryErrors and then decref them, which will fill
@@ -2309,12 +2309,14 @@ preallocate_memerrors(void)
for (i = 0; i < MEMERRORS_SAVE; i++) {
errors[i] = MemoryError_new((PyTypeObject *) PyExc_MemoryError,
NULL, NULL);
- if (!errors[i])
- Py_FatalError("Could not preallocate MemoryError object");
+ if (!errors[i]) {
+ return -1;
+ }
}
for (i = 0; i < MEMERRORS_SAVE; i++) {
Py_DECREF(errors[i]);
}
+ return 0;
}
static void
@@ -2433,31 +2435,6 @@ SimpleExtendsException(PyExc_Warning, ResourceWarning,
-#define PRE_INIT(TYPE) \
- if (!(_PyExc_ ## TYPE.tp_flags & Py_TPFLAGS_READY)) { \
- if (PyType_Ready(&_PyExc_ ## TYPE) < 0) \
- Py_FatalError("exceptions bootstrapping error."); \
- Py_INCREF(PyExc_ ## TYPE); \
- }
-
-#define POST_INIT(TYPE) \
- if (PyDict_SetItemString(bdict, # TYPE, PyExc_ ## TYPE)) \
- Py_FatalError("Module dictionary insertion problem.");
-
-#define INIT_ALIAS(NAME, TYPE) Py_INCREF(PyExc_ ## TYPE); \
- Py_XDECREF(PyExc_ ## NAME); \
- PyExc_ ## NAME = PyExc_ ## TYPE; \
- if (PyDict_SetItemString(bdict, # NAME, PyExc_ ## NAME)) \
- Py_FatalError("Module dictionary insertion problem.");
-
-#define ADD_ERRNO(TYPE, CODE) { \
- PyObject *_code = PyLong_FromLong(CODE); \
- assert(_PyObject_RealIsSubclass(PyExc_ ## TYPE, PyExc_OSError)); \
- if (!_code || PyDict_SetItem(errnomap, _code, PyExc_ ## TYPE)) \
- Py_FatalError("errmap insertion problem."); \
- Py_DECREF(_code); \
- }
-
#ifdef MS_WINDOWS
#include <winsock2.h>
/* The following constants were added to errno.h in VS2010 but have
@@ -2514,184 +2491,226 @@ SimpleExtendsException(PyExc_Warning, ResourceWarning,
#endif
#endif /* MS_WINDOWS */
-void
+_PyInitError
_PyExc_Init(PyObject *bltinmod)
{
+#define PRE_INIT(TYPE) \
+ if (!(_PyExc_ ## TYPE.tp_flags & Py_TPFLAGS_READY)) { \
+ if (PyType_Ready(&_PyExc_ ## TYPE) < 0) { \
+ return _Py_INIT_ERR("exceptions bootstrapping error."); \
+ } \
+ Py_INCREF(PyExc_ ## TYPE); \
+ }
+
+#define POST_INIT(TYPE) \
+ if (PyDict_SetItemString(bdict, # TYPE, PyExc_ ## TYPE)) { \
+ return _Py_INIT_ERR("Module dictionary insertion problem."); \
+ }
+
+#define INIT_ALIAS(NAME, TYPE) \
+ do { \
+ Py_INCREF(PyExc_ ## TYPE); \
+ Py_XDECREF(PyExc_ ## NAME); \
+ PyExc_ ## NAME = PyExc_ ## TYPE; \
+ if (PyDict_SetItemString(bdict, # NAME, PyExc_ ## NAME)) { \
+ return _Py_INIT_ERR("Module dictionary insertion problem."); \
+ } \
+ } while (0)
+
+#define ADD_ERRNO(TYPE, CODE) \
+ do { \
+ PyObject *_code = PyLong_FromLong(CODE); \
+ assert(_PyObject_RealIsSubclass(PyExc_ ## TYPE, PyExc_OSError)); \
+ if (!_code || PyDict_SetItem(errnomap, _code, PyExc_ ## TYPE)) \
+ return _Py_INIT_ERR("errmap insertion problem."); \
+ Py_DECREF(_code); \
+ } while (0)
+
PyObject *bdict;
- PRE_INIT(BaseException)
- PRE_INIT(Exception)
- PRE_INIT(TypeError)
- PRE_INIT(StopAsyncIteration)
- PRE_INIT(StopIteration)
- PRE_INIT(GeneratorExit)
- PRE_INIT(SystemExit)
- PRE_INIT(KeyboardInterrupt)
- PRE_INIT(ImportError)
- PRE_INIT(ModuleNotFoundError)
- PRE_INIT(OSError)
- PRE_INIT(EOFError)
- PRE_INIT(RuntimeError)
- PRE_INIT(RecursionError)
- PRE_INIT(NotImplementedError)
- PRE_INIT(NameError)
- PRE_INIT(UnboundLocalError)
- PRE_INIT(AttributeError)
- PRE_INIT(SyntaxError)
- PRE_INIT(IndentationError)
- PRE_INIT(TabError)
- PRE_INIT(LookupError)
- PRE_INIT(IndexError)
- PRE_INIT(KeyError)
- PRE_INIT(ValueError)
- PRE_INIT(UnicodeError)
- PRE_INIT(UnicodeEncodeError)
- PRE_INIT(UnicodeDecodeError)
- PRE_INIT(UnicodeTranslateError)
- PRE_INIT(AssertionError)
- PRE_INIT(ArithmeticError)
- PRE_INIT(FloatingPointError)
- PRE_INIT(OverflowError)
- PRE_INIT(ZeroDivisionError)
- PRE_INIT(SystemError)
- PRE_INIT(ReferenceError)
- PRE_INIT(MemoryError)
- PRE_INIT(BufferError)
- PRE_INIT(Warning)
- PRE_INIT(UserWarning)
- PRE_INIT(DeprecationWarning)
- PRE_INIT(PendingDeprecationWarning)
- PRE_INIT(SyntaxWarning)
- PRE_INIT(RuntimeWarning)
- PRE_INIT(FutureWarning)
- PRE_INIT(ImportWarning)
- PRE_INIT(UnicodeWarning)
- PRE_INIT(BytesWarning)
- PRE_INIT(ResourceWarning)
+ PRE_INIT(BaseException);
+ PRE_INIT(Exception);
+ PRE_INIT(TypeError);
+ PRE_INIT(StopAsyncIteration);
+ PRE_INIT(StopIteration);
+ PRE_INIT(GeneratorExit);
+ PRE_INIT(SystemExit);
+ PRE_INIT(KeyboardInterrupt);
+ PRE_INIT(ImportError);
+ PRE_INIT(ModuleNotFoundError);
+ PRE_INIT(OSError);
+ PRE_INIT(EOFError);
+ PRE_INIT(RuntimeError);
+ PRE_INIT(RecursionError);
+ PRE_INIT(NotImplementedError);
+ PRE_INIT(NameError);
+ PRE_INIT(UnboundLocalError);
+ PRE_INIT(AttributeError);
+ PRE_INIT(SyntaxError);
+ PRE_INIT(IndentationError);
+ PRE_INIT(TabError);
+ PRE_INIT(LookupError);
+ PRE_INIT(IndexError);
+ PRE_INIT(KeyError);
+ PRE_INIT(ValueError);
+ PRE_INIT(UnicodeError);
+ PRE_INIT(UnicodeEncodeError);
+ PRE_INIT(UnicodeDecodeError);
+ PRE_INIT(UnicodeTranslateError);
+ PRE_INIT(AssertionError);
+ PRE_INIT(ArithmeticError);
+ PRE_INIT(FloatingPointError);
+ PRE_INIT(OverflowError);
+ PRE_INIT(ZeroDivisionError);
+ PRE_INIT(SystemError);
+ PRE_INIT(ReferenceError);
+ PRE_INIT(MemoryError);
+ PRE_INIT(BufferError);
+ PRE_INIT(Warning);
+ PRE_INIT(UserWarning);
+ PRE_INIT(DeprecationWarning);
+ PRE_INIT(PendingDeprecationWarning);
+ PRE_INIT(SyntaxWarning);
+ PRE_INIT(RuntimeWarning);
+ PRE_INIT(FutureWarning);
+ PRE_INIT(ImportWarning);
+ PRE_INIT(UnicodeWarning);
+ PRE_INIT(BytesWarning);
+ PRE_INIT(ResourceWarning);
/* OSError subclasses */
- PRE_INIT(ConnectionError)
-
- PRE_INIT(BlockingIOError)
- PRE_INIT(BrokenPipeError)
- PRE_INIT(ChildProcessError)
- PRE_INIT(ConnectionAbortedError)
- PRE_INIT(ConnectionRefusedError)
- PRE_INIT(ConnectionResetError)
- PRE_INIT(FileExistsError)
- PRE_INIT(FileNotFoundError)
- PRE_INIT(IsADirectoryError)
- PRE_INIT(NotADirectoryError)
- PRE_INIT(InterruptedError)
- PRE_INIT(PermissionError)
- PRE_INIT(ProcessLookupError)
- PRE_INIT(TimeoutError)
+ PRE_INIT(ConnectionError);
+
+ PRE_INIT(BlockingIOError);
+ PRE_INIT(BrokenPipeError);
+ PRE_INIT(ChildProcessError);
+ PRE_INIT(ConnectionAbortedError);
+ PRE_INIT(ConnectionRefusedError);
+ PRE_INIT(ConnectionResetError);
+ PRE_INIT(FileExistsError);
+ PRE_INIT(FileNotFoundError);
+ PRE_INIT(IsADirectoryError);
+ PRE_INIT(NotADirectoryError);
+ PRE_INIT(InterruptedError);
+ PRE_INIT(PermissionError);
+ PRE_INIT(ProcessLookupError);
+ PRE_INIT(TimeoutError);
bdict = PyModule_GetDict(bltinmod);
- if (bdict == NULL)
- Py_FatalError("exceptions bootstrapping error.");
-
- POST_INIT(BaseException)
- POST_INIT(Exception)
- POST_INIT(TypeError)
- POST_INIT(StopAsyncIteration)
- POST_INIT(StopIteration)
- POST_INIT(GeneratorExit)
- POST_INIT(SystemExit)
- POST_INIT(KeyboardInterrupt)
- POST_INIT(ImportError)
- POST_INIT(ModuleNotFoundError)
- POST_INIT(OSError)
- INIT_ALIAS(EnvironmentError, OSError)
- INIT_ALIAS(IOError, OSError)
+ if (bdict == NULL) {
+ return _Py_INIT_ERR("exceptions bootstrapping error.");
+ }
+
+ POST_INIT(BaseException);
+ POST_INIT(Exception);
+ POST_INIT(TypeError);
+ POST_INIT(StopAsyncIteration);
+ POST_INIT(StopIteration);
+ POST_INIT(GeneratorExit);
+ POST_INIT(SystemExit);
+ POST_INIT(KeyboardInterrupt);
+ POST_INIT(ImportError);
+ POST_INIT(ModuleNotFoundError);
+ POST_INIT(OSError);
+ INIT_ALIAS(EnvironmentError, OSError);
+ INIT_ALIAS(IOError, OSError);
#ifdef MS_WINDOWS
- INIT_ALIAS(WindowsError, OSError)
+ INIT_ALIAS(WindowsError, OSError);
#endif
- POST_INIT(EOFError)
- POST_INIT(RuntimeError)
- POST_INIT(RecursionError)
- POST_INIT(NotImplementedError)
- POST_INIT(NameError)
- POST_INIT(UnboundLocalError)
- POST_INIT(AttributeError)
- POST_INIT(SyntaxError)
- POST_INIT(IndentationError)
- POST_INIT(TabError)
- POST_INIT(LookupError)
- POST_INIT(IndexError)
- POST_INIT(KeyError)
- POST_INIT(ValueError)
- POST_INIT(UnicodeError)
- POST_INIT(UnicodeEncodeError)
- POST_INIT(UnicodeDecodeError)
- POST_INIT(UnicodeTranslateError)
- POST_INIT(AssertionError)
- POST_INIT(ArithmeticError)
- POST_INIT(FloatingPointError)
- POST_INIT(OverflowError)
- POST_INIT(ZeroDivisionError)
- POST_INIT(SystemError)
- POST_INIT(ReferenceError)
- POST_INIT(MemoryError)
- POST_INIT(BufferError)
- POST_INIT(Warning)
- POST_INIT(UserWarning)
- POST_INIT(DeprecationWarning)
- POST_INIT(PendingDeprecationWarning)
- POST_INIT(SyntaxWarning)
- POST_INIT(RuntimeWarning)
- POST_INIT(FutureWarning)
- POST_INIT(ImportWarning)
- POST_INIT(UnicodeWarning)
- POST_INIT(BytesWarning)
- POST_INIT(ResourceWarning)
+ POST_INIT(EOFError);
+ POST_INIT(RuntimeError);
+ POST_INIT(RecursionError);
+ POST_INIT(NotImplementedError);
+ POST_INIT(NameError);
+ POST_INIT(UnboundLocalError);
+ POST_INIT(AttributeError);
+ POST_INIT(SyntaxError);
+ POST_INIT(IndentationError);
+ POST_INIT(TabError);
+ POST_INIT(LookupError);
+ POST_INIT(IndexError);
+ POST_INIT(KeyError);
+ POST_INIT(ValueError);
+ POST_INIT(UnicodeError);
+ POST_INIT(UnicodeEncodeError);
+ POST_INIT(UnicodeDecodeError);
+ POST_INIT(UnicodeTranslateError);
+ POST_INIT(AssertionError);
+ POST_INIT(ArithmeticError);
+ POST_INIT(FloatingPointError);
+ POST_INIT(OverflowError);
+ POST_INIT(ZeroDivisionError);
+ POST_INIT(SystemError);
+ POST_INIT(ReferenceError);
+ POST_INIT(MemoryError);
+ POST_INIT(BufferError);
+ POST_INIT(Warning);
+ POST_INIT(UserWarning);
+ POST_INIT(DeprecationWarning);
+ POST_INIT(PendingDeprecationWarning);
+ POST_INIT(SyntaxWarning);
+ POST_INIT(RuntimeWarning);
+ POST_INIT(FutureWarning);
+ POST_INIT(ImportWarning);
+ POST_INIT(UnicodeWarning);
+ POST_INIT(BytesWarning);
+ POST_INIT(ResourceWarning);
if (!errnomap) {
errnomap = PyDict_New();
- if (!errnomap)
- Py_FatalError("Cannot allocate map from errnos to OSError subclasses");
+ if (!errnomap) {
+ return _Py_INIT_ERR("Cannot allocate map from errnos to OSError subclasses");
+ }
}
/* OSError subclasses */
- POST_INIT(ConnectionError)
-
- POST_INIT(BlockingIOError)
- ADD_ERRNO(BlockingIOError, EAGAIN)
- ADD_ERRNO(BlockingIOError, EALREADY)
- ADD_ERRNO(BlockingIOError, EINPROGRESS)
- ADD_ERRNO(BlockingIOError, EWOULDBLOCK)
- POST_INIT(BrokenPipeError)
- ADD_ERRNO(BrokenPipeError, EPIPE)
+ POST_INIT(ConnectionError);
+
+ POST_INIT(BlockingIOError);
+ ADD_ERRNO(BlockingIOError, EAGAIN);
+ ADD_ERRNO(BlockingIOError, EALREADY);
+ ADD_ERRNO(BlockingIOError, EINPROGRESS);
+ ADD_ERRNO(BlockingIOError, EWOULDBLOCK);
+ POST_INIT(BrokenPipeError);
+ ADD_ERRNO(BrokenPipeError, EPIPE);
#ifdef ESHUTDOWN
- ADD_ERRNO(BrokenPipeError, ESHUTDOWN)
+ ADD_ERRNO(BrokenPipeError, ESHUTDOWN);
#endif
- POST_INIT(ChildProcessError)
- ADD_ERRNO(ChildProcessError, ECHILD)
- POST_INIT(ConnectionAbortedError)
- ADD_ERRNO(ConnectionAbortedError, ECONNABORTED)
- POST_INIT(ConnectionRefusedError)
- ADD_ERRNO(ConnectionRefusedError, ECONNREFUSED)
- POST_INIT(ConnectionResetError)
- ADD_ERRNO(ConnectionResetError, ECONNRESET)
- POST_INIT(FileExistsError)
- ADD_ERRNO(FileExistsError, EEXIST)
- POST_INIT(FileNotFoundError)
- ADD_ERRNO(FileNotFoundError, ENOENT)
- POST_INIT(IsADirectoryError)
- ADD_ERRNO(IsADirectoryError, EISDIR)
- POST_INIT(NotADirectoryError)
- ADD_ERRNO(NotADirectoryError, ENOTDIR)
- POST_INIT(InterruptedError)
- ADD_ERRNO(InterruptedError, EINTR)
- POST_INIT(PermissionError)
- ADD_ERRNO(PermissionError, EACCES)
- ADD_ERRNO(PermissionError, EPERM)
- POST_INIT(ProcessLookupError)
- ADD_ERRNO(ProcessLookupError, ESRCH)
- POST_INIT(TimeoutError)
- ADD_ERRNO(TimeoutError, ETIMEDOUT)
-
- preallocate_memerrors();
+ POST_INIT(ChildProcessError);
+ ADD_ERRNO(ChildProcessError, ECHILD);
+ POST_INIT(ConnectionAbortedError);
+ ADD_ERRNO(ConnectionAbortedError, ECONNABORTED);
+ POST_INIT(ConnectionRefusedError);
+ ADD_ERRNO(ConnectionRefusedError, ECONNREFUSED);
+ POST_INIT(ConnectionResetError);
+ ADD_ERRNO(ConnectionResetError, ECONNRESET);
+ POST_INIT(FileExistsError);
+ ADD_ERRNO(FileExistsError, EEXIST);
+ POST_INIT(FileNotFoundError);
+ ADD_ERRNO(FileNotFoundError, ENOENT);
+ POST_INIT(IsADirectoryError);
+ ADD_ERRNO(IsADirectoryError, EISDIR);
+ POST_INIT(NotADirectoryError);
+ ADD_ERRNO(NotADirectoryError, ENOTDIR);
+ POST_INIT(InterruptedError);
+ ADD_ERRNO(InterruptedError, EINTR);
+ POST_INIT(PermissionError);
+ ADD_ERRNO(PermissionError, EACCES);
+ ADD_ERRNO(PermissionError, EPERM);
+ POST_INIT(ProcessLookupError);
+ ADD_ERRNO(ProcessLookupError, ESRCH);
+ POST_INIT(TimeoutError);
+ ADD_ERRNO(TimeoutError, ETIMEDOUT);
+
+ if (preallocate_memerrors() < 0) {
+ return _Py_INIT_ERR("Could not preallocate MemoryError object");
+ }
+ return _Py_INIT_OK();
+
+#undef PRE_INIT
+#undef POST_INIT
+#undef INIT_ALIAS
+#undef ADD_ERRNO
}
void