[Python-checkins] bpo-35713: Rework Python initialization (GH-11647)

Victor Stinner webhook-mailer at python.org
Tue Jan 22 11:39:07 EST 2019


https://github.com/python/cpython/commit/bf4ac2d2fd520c61306b2676db488adab9b5d8c5
commit: bf4ac2d2fd520c61306b2676db488adab9b5d8c5
branch: master
author: Victor Stinner <vstinner at redhat.com>
committer: GitHub <noreply at github.com>
date: 2019-01-22T17:39:03+01:00
summary:

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().

files:
A Misc/NEWS.d/next/C API/2019-01-22-17-04-10.bpo-35713.fmehdG.rst
M Doc/whatsnew/3.8.rst
M Include/cpython/pylifecycle.h
M Include/internal/pycore_pylifecycle.h
M Objects/bytearrayobject.c
M Objects/exceptions.c
M Objects/unicodeobject.c
M Python/pylifecycle.c
M Python/sysmodule.c

diff --git a/Doc/whatsnew/3.8.rst b/Doc/whatsnew/3.8.rst
index 0360be604f56..8b38cce35368 100644
--- a/Doc/whatsnew/3.8.rst
+++ b/Doc/whatsnew/3.8.rst
@@ -328,6 +328,10 @@ Optimizations
 Build and C API Changes
 =======================
 
+* The :c:func:`PyByteArray_Init` and :c:func:`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.
+
 * The result of :c:func:`PyExceptionClass_Name` is now of type
   ``const char *`` rather of ``char *``.
   (Contributed by Serhiy Storchaka in :issue:`33818`.)
diff --git a/Include/cpython/pylifecycle.h b/Include/cpython/pylifecycle.h
index 3009c4f10d3a..a3fdeefde01b 100644
--- a/Include/cpython/pylifecycle.h
+++ b/Include/cpython/pylifecycle.h
@@ -56,33 +56,6 @@ PyAPI_FUNC(void) _Py_SetProgramFullPath(const wchar_t *);
 PyAPI_FUNC(const char *) _Py_gitidentifier(void);
 PyAPI_FUNC(const char *) _Py_gitversion(void);
 
-/* Internal -- various one-time initializations */
-PyAPI_FUNC(PyObject *) _PyBuiltin_Init(void);
-PyAPI_FUNC(_PyInitError) _PySys_BeginInit(PyObject **sysmod);
-PyAPI_FUNC(int) _PySys_EndInit(PyObject *sysdict, PyInterpreterState *interp);
-PyAPI_FUNC(_PyInitError) _PyImport_Init(PyInterpreterState *interp);
-PyAPI_FUNC(void) _PyExc_Init(PyObject * bltinmod);
-PyAPI_FUNC(_PyInitError) _PyImportHooks_Init(void);
-PyAPI_FUNC(int) _PyFloat_Init(void);
-PyAPI_FUNC(int) PyByteArray_Init(void);
-PyAPI_FUNC(_PyInitError) _Py_HashRandomization_Init(const _PyCoreConfig *);
-
-/* Various internal finalizers */
-
-PyAPI_FUNC(void) PyMethod_Fini(void);
-PyAPI_FUNC(void) PyFrame_Fini(void);
-PyAPI_FUNC(void) PyCFunction_Fini(void);
-PyAPI_FUNC(void) PyDict_Fini(void);
-PyAPI_FUNC(void) PyTuple_Fini(void);
-PyAPI_FUNC(void) PyList_Fini(void);
-PyAPI_FUNC(void) PySet_Fini(void);
-PyAPI_FUNC(void) PyBytes_Fini(void);
-PyAPI_FUNC(void) PyByteArray_Fini(void);
-PyAPI_FUNC(void) PyFloat_Fini(void);
-PyAPI_FUNC(void) PyOS_FiniInterrupts(void);
-PyAPI_FUNC(void) PySlice_Fini(void);
-PyAPI_FUNC(void) PyAsyncGen_Fini(void);
-
 PyAPI_FUNC(int) _Py_IsFinalizing(void);
 
 /* Random */
diff --git a/Include/internal/pycore_pylifecycle.h b/Include/internal/pycore_pylifecycle.h
index e10431690cbd..de70199dae57 100644
--- a/Include/internal/pycore_pylifecycle.h
+++ b/Include/internal/pycore_pylifecycle.h
@@ -19,20 +19,45 @@ PyAPI_FUNC(void) _Py_ClearStandardStreamEncoding(void);
 
 PyAPI_FUNC(int) _Py_IsLocaleCoercionTarget(const char *ctype_loc);
 
-extern int _PyUnicode_Init(void);
+/* Various one-time initializers */
+
+extern _PyInitError _PyUnicode_Init(void);
 extern int _PyStructSequence_Init(void);
 extern int _PyLong_Init(void);
 extern _PyInitError _PyFaulthandler_Init(int enable);
 extern int _PyTraceMalloc_Init(int enable);
+extern PyObject * _PyBuiltin_Init(void);
+extern _PyInitError _PySys_BeginInit(PyObject **sysmod);
+extern int _PySys_EndInit(PyObject *sysdict, PyInterpreterState *interp);
+extern _PyInitError _PyImport_Init(PyInterpreterState *interp);
+extern _PyInitError _PyExc_Init(PyObject * bltinmod);
+extern _PyInitError _PyImportHooks_Init(void);
+extern int _PyFloat_Init(void);
+extern _PyInitError _Py_HashRandomization_Init(const _PyCoreConfig *);
 
 extern void _Py_ReadyTypes(void);
 
-PyAPI_FUNC(void) _PyExc_Fini(void);
-PyAPI_FUNC(void) _PyImport_Fini(void);
-PyAPI_FUNC(void) _PyImport_Fini2(void);
-PyAPI_FUNC(void) _PyGC_Fini(void);
-PyAPI_FUNC(void) _PyType_Fini(void);
-PyAPI_FUNC(void) _Py_HashRandomization_Fini(void);
+/* Various internal finalizers */
+
+extern void PyMethod_Fini(void);
+extern void PyFrame_Fini(void);
+extern void PyCFunction_Fini(void);
+extern void PyDict_Fini(void);
+extern void PyTuple_Fini(void);
+extern void PyList_Fini(void);
+extern void PySet_Fini(void);
+extern void PyBytes_Fini(void);
+extern void PyFloat_Fini(void);
+extern void PyOS_FiniInterrupts(void);
+extern void PySlice_Fini(void);
+extern void PyAsyncGen_Fini(void);
+
+extern void _PyExc_Fini(void);
+extern void _PyImport_Fini(void);
+extern void _PyImport_Fini2(void);
+extern void _PyGC_Fini(void);
+extern void _PyType_Fini(void);
+extern void _Py_HashRandomization_Fini(void);
 extern void _PyUnicode_Fini(void);
 extern void PyLong_Fini(void);
 extern void _PyFaulthandler_Fini(void);
diff --git a/Misc/NEWS.d/next/C API/2019-01-22-17-04-10.bpo-35713.fmehdG.rst b/Misc/NEWS.d/next/C API/2019-01-22-17-04-10.bpo-35713.fmehdG.rst
new file mode 100644
index 000000000000..f95ceca47fdf
--- /dev/null
+++ b/Misc/NEWS.d/next/C API/2019-01-22-17-04-10.bpo-35713.fmehdG.rst	
@@ -0,0 +1,3 @@
+The :c:func:`PyByteArray_Init` and :c:func:`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.
diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c
index 3926095a1812..667213619344 100644
--- a/Objects/bytearrayobject.c
+++ b/Objects/bytearrayobject.c
@@ -17,17 +17,6 @@ class bytearray "PyByteArrayObject *" "&PyByteArray_Type"
 
 char _PyByteArray_empty_string[] = "";
 
-void
-PyByteArray_Fini(void)
-{
-}
-
-int
-PyByteArray_Init(void)
-{
-    return 1;
-}
-
 /* end nullbytes support */
 
 /* Helpers */
diff --git a/Objects/exceptions.c b/Objects/exceptions.c
index 002a602373d7..8d81566c7f15 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
diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c
index f1d23b66fa14..ea7bcabfc64f 100644
--- a/Objects/unicodeobject.c
+++ b/Objects/unicodeobject.c
@@ -15199,7 +15199,8 @@ PyTypeObject PyUnicode_Type = {
 
 /* Initialize the Unicode implementation */
 
-int _PyUnicode_Init(void)
+_PyInitError
+_PyUnicode_Init(void)
 {
     /* XXX - move this array to unicodectype.c ? */
     Py_UCS2 linebreak[] = {
@@ -15215,28 +15216,31 @@ int _PyUnicode_Init(void)
 
     /* Init the implementation */
     _Py_INCREF_UNICODE_EMPTY();
-    if (!unicode_empty)
-        Py_FatalError("Can't create empty string");
+    if (!unicode_empty) {
+        return _Py_INIT_ERR("Can't create empty string");
+    }
     Py_DECREF(unicode_empty);
 
-    if (PyType_Ready(&PyUnicode_Type) < 0)
-        Py_FatalError("Can't initialize 'unicode'");
+    if (PyType_Ready(&PyUnicode_Type) < 0) {
+        return _Py_INIT_ERR("Can't initialize unicode type");
+    }
 
     /* initialize the linebreak bloom filter */
     bloom_linebreak = make_bloom_mask(
         PyUnicode_2BYTE_KIND, linebreak,
         Py_ARRAY_LENGTH(linebreak));
 
-    if (PyType_Ready(&EncodingMapType) < 0)
-         Py_FatalError("Can't initialize encoding map type");
-
-    if (PyType_Ready(&PyFieldNameIter_Type) < 0)
-        Py_FatalError("Can't initialize field name iterator type");
-
-    if (PyType_Ready(&PyFormatterIter_Type) < 0)
-        Py_FatalError("Can't initialize formatter iter type");
+    if (PyType_Ready(&EncodingMapType) < 0) {
+         return _Py_INIT_ERR("Can't initialize encoding map type");
+    }
+    if (PyType_Ready(&PyFieldNameIter_Type) < 0) {
+        return _Py_INIT_ERR("Can't initialize field name iterator type");
+    }
+    if (PyType_Ready(&PyFormatterIter_Type) < 0) {
+        return _Py_INIT_ERR("Can't initialize formatter iter type");
+    }
 
-    return 0;
+    return _Py_INIT_OK();
 }
 
 /* Finalize the Unicode implementation */
diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c
index 37ecc510c8fb..f0e00ea48d48 100644
--- a/Python/pylifecycle.c
+++ b/Python/pylifecycle.c
@@ -608,9 +608,6 @@ _Py_InitializeCore_impl(PyInterpreterState **interp_p,
     if (!_PyLong_Init())
         return _Py_INIT_ERR("can't init longs");
 
-    if (!PyByteArray_Init())
-        return _Py_INIT_ERR("can't init bytearray");
-
     if (!_PyFloat_Init())
         return _Py_INIT_ERR("can't init float");
 
@@ -634,9 +631,10 @@ _Py_InitializeCore_impl(PyInterpreterState **interp_p,
     PyDict_SetItemString(interp->sysdict, "modules", modules);
     _PyImport_FixupBuiltin(sysmod, "sys", modules);
 
-    /* Init Unicode implementation; relies on the codec registry */
-    if (_PyUnicode_Init() < 0)
-        return _Py_INIT_ERR("can't initialize unicode");
+    err = _PyUnicode_Init();
+    if (_Py_INIT_FAILED(err)) {
+        return err;
+    }
 
     if (_PyStructSequence_Init() < 0)
         return _Py_INIT_ERR("can't initialize structseq");
@@ -651,7 +649,10 @@ _Py_InitializeCore_impl(PyInterpreterState **interp_p,
     Py_INCREF(interp->builtins);
 
     /* initialize builtin exceptions */
-    _PyExc_Init(bimod);
+    err = _PyExc_Init(bimod);
+    if (_Py_INIT_FAILED(err)) {
+        return err;
+    }
 
     /* Set up a preliminary stderr printer until we have enough
        infrastructure for the io module in place. */
@@ -1146,7 +1147,6 @@ Py_FinalizeEx(void)
     PyList_Fini();
     PySet_Fini();
     PyBytes_Fini();
-    PyByteArray_Fini();
     PyLong_Fini();
     PyFloat_Fini();
     PyDict_Fini();
@@ -1302,7 +1302,10 @@ new_interpreter(PyThreadState **tstate_p)
     }
 
     /* initialize builtin exceptions */
-    _PyExc_Init(bimod);
+    err = _PyExc_Init(bimod);
+    if (_Py_INIT_FAILED(err)) {
+        return err;
+    }
 
     if (bimod != NULL && sysmod != NULL) {
         PyObject *pstderr;
@@ -1682,6 +1685,20 @@ init_sys_streams(PyInterpreterState *interp)
     _PyInitError res = _Py_INIT_OK();
     _PyCoreConfig *config = &interp->core_config;
 
+    /* Check that stdin is not a directory
+       Using shell redirection, you can redirect stdin to a directory,
+       crashing the Python interpreter. Catch this common mistake here
+       and output a useful error message. Note that under MS Windows,
+       the shell already prevents that. */
+#ifndef MS_WINDOWS
+    struct _Py_stat_struct sb;
+    if (_Py_fstat_noraise(fileno(stdin), &sb) == 0 &&
+        S_ISDIR(sb.st_mode)) {
+        return _Py_INIT_USER_ERR("<stdin> is a directory, "
+                                 "cannot continue");
+    }
+#endif
+
     char *codec_name = get_codec_name(config->stdio_encoding);
     if (codec_name == NULL) {
         return _Py_INIT_ERR("failed to get the Python codec name "
diff --git a/Python/sysmodule.c b/Python/sysmodule.c
index 5ea3772efded..8efe1699422c 100644
--- a/Python/sysmodule.c
+++ b/Python/sysmodule.c
@@ -2381,22 +2381,6 @@ _PySys_BeginInit(PyObject **sysmod)
     }
     sysdict = PyModule_GetDict(m);
 
-    /* Check that stdin is not a directory
-       Using shell redirection, you can redirect stdin to a directory,
-       crashing the Python interpreter. Catch this common mistake here
-       and output a useful error message. Note that under MS Windows,
-       the shell already prevents that. */
-#ifndef MS_WINDOWS
-    {
-        struct _Py_stat_struct sb;
-        if (_Py_fstat_noraise(fileno(stdin), &sb) == 0 &&
-            S_ISDIR(sb.st_mode)) {
-            return _Py_INIT_USER_ERR("<stdin> is a directory, "
-                                     "cannot continue");
-        }
-    }
-#endif
-
     /* stdin/stdout/stderr are set in pylifecycle.c */
 
     SET_SYS_FROM_STRING_BORROW("__displayhook__",



More information about the Python-checkins mailing list