aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/tools/python3/src/Python/pylifecycle.c
diff options
context:
space:
mode:
authororivej <orivej@yandex-team.ru>2022-02-10 16:44:49 +0300
committerDaniil Cherednik <dcherednik@yandex-team.ru>2022-02-10 16:44:49 +0300
commit718c552901d703c502ccbefdfc3c9028d608b947 (patch)
tree46534a98bbefcd7b1f3faa5b52c138ab27db75b7 /contrib/tools/python3/src/Python/pylifecycle.c
parente9656aae26e0358d5378e5b63dcac5c8dbe0e4d0 (diff)
downloadydb-718c552901d703c502ccbefdfc3c9028d608b947.tar.gz
Restoring authorship annotation for <orivej@yandex-team.ru>. Commit 1 of 2.
Diffstat (limited to 'contrib/tools/python3/src/Python/pylifecycle.c')
-rw-r--r--contrib/tools/python3/src/Python/pylifecycle.c2716
1 files changed, 1358 insertions, 1358 deletions
diff --git a/contrib/tools/python3/src/Python/pylifecycle.c b/contrib/tools/python3/src/Python/pylifecycle.c
index 7f591179ac..0103610261 100644
--- a/contrib/tools/python3/src/Python/pylifecycle.c
+++ b/contrib/tools/python3/src/Python/pylifecycle.c
@@ -1,10 +1,10 @@
-/* Python interpreter top-level routines, including init/exit */
-
-#include "Python.h"
-
-#include "Python-ast.h"
+/* Python interpreter top-level routines, including init/exit */
+
+#include "Python.h"
+
+#include "Python-ast.h"
#undef Yield /* undefine macro conflicting with <winbase.h> */
-
+
#include "pycore_ceval.h" // _PyEval_FiniGIL()
#include "pycore_context.h" // _PyContext_Init()
#include "pycore_fileutils.h" // _Py_ResetForceASCII()
@@ -21,37 +21,37 @@
#include "grammar.h" // PyGrammar_RemoveAccelerators()
#include <locale.h> // setlocale()
-#ifdef HAVE_SIGNAL_H
+#ifdef HAVE_SIGNAL_H
# include <signal.h> // SIG_IGN
-#endif
-
-#ifdef HAVE_LANGINFO_H
+#endif
+
+#ifdef HAVE_LANGINFO_H
# include <langinfo.h> // nl_langinfo(CODESET)
-#endif
-
-#ifdef MS_WINDOWS
+#endif
+
+#ifdef MS_WINDOWS
# undef BYTE
# include "windows.h"
-
+
extern PyTypeObject PyWindowsConsoleIO_Type;
# define PyWindowsConsoleIO_Check(op) \
(PyObject_TypeCheck((op), &PyWindowsConsoleIO_Type))
-#endif
-
-
-_Py_IDENTIFIER(flush);
-_Py_IDENTIFIER(name);
-_Py_IDENTIFIER(stdin);
-_Py_IDENTIFIER(stdout);
-_Py_IDENTIFIER(stderr);
-_Py_IDENTIFIER(threading);
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-extern grammar _PyParser_Grammar; /* From graminit.c */
-
+#endif
+
+
+_Py_IDENTIFIER(flush);
+_Py_IDENTIFIER(name);
+_Py_IDENTIFIER(stdin);
+_Py_IDENTIFIER(stdout);
+_Py_IDENTIFIER(stderr);
+_Py_IDENTIFIER(threading);
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern grammar _PyParser_Grammar; /* From graminit.c */
+
/* Forward declarations */
static PyStatus add_main_module(PyInterpreterState *interp);
static PyStatus init_import_site(void);
@@ -60,182 +60,182 @@ static PyStatus init_sys_streams(PyThreadState *tstate);
static void call_py_exitfuncs(PyThreadState *tstate);
static void wait_for_thread_shutdown(PyThreadState *tstate);
static void call_ll_exitfuncs(_PyRuntimeState *runtime);
-
+
int _Py_UnhandledKeyboardInterrupt = 0;
-_PyRuntimeState _PyRuntime = _PyRuntimeState_INIT;
+_PyRuntimeState _PyRuntime = _PyRuntimeState_INIT;
static int runtime_initialized = 0;
-
+
PyStatus
-_PyRuntime_Initialize(void)
-{
- /* XXX We only initialize once in the process, which aligns with
- the static initialization of the former globals now found in
- _PyRuntime. However, _PyRuntime *should* be initialized with
- every Py_Initialize() call, but doing so breaks the runtime.
- This is because the runtime state is not properly finalized
- currently. */
+_PyRuntime_Initialize(void)
+{
+ /* XXX We only initialize once in the process, which aligns with
+ the static initialization of the former globals now found in
+ _PyRuntime. However, _PyRuntime *should* be initialized with
+ every Py_Initialize() call, but doing so breaks the runtime.
+ This is because the runtime state is not properly finalized
+ currently. */
if (runtime_initialized) {
return _PyStatus_OK();
- }
+ }
runtime_initialized = 1;
-
- return _PyRuntimeState_Init(&_PyRuntime);
-}
-
-void
-_PyRuntime_Finalize(void)
-{
- _PyRuntimeState_Fini(&_PyRuntime);
+
+ return _PyRuntimeState_Init(&_PyRuntime);
+}
+
+void
+_PyRuntime_Finalize(void)
+{
+ _PyRuntimeState_Fini(&_PyRuntime);
runtime_initialized = 0;
-}
-
-int
-_Py_IsFinalizing(void)
-{
+}
+
+int
+_Py_IsFinalizing(void)
+{
return _PyRuntimeState_GetFinalizing(&_PyRuntime) != NULL;
-}
-
-/* Hack to force loading of object files */
-int (*_PyOS_mystrnicmp_hack)(const char *, const char *, Py_ssize_t) = \
- PyOS_mystrnicmp; /* Python/pystrcmp.o */
-
-/* PyModule_GetWarningsModule is no longer necessary as of 2.6
-since _warnings is builtin. This API should not be used. */
-PyObject *
-PyModule_GetWarningsModule(void)
-{
- return PyImport_ImportModule("warnings");
-}
-
-
-/* APIs to access the initialization flags
- *
- * Can be called prior to Py_Initialize.
- */
-
-int
-_Py_IsCoreInitialized(void)
-{
- return _PyRuntime.core_initialized;
-}
-
-int
-Py_IsInitialized(void)
-{
- return _PyRuntime.initialized;
-}
-
-
-/* Global initializations. Can be undone by Py_FinalizeEx(). Don't
- call this twice without an intervening Py_FinalizeEx() call. When
- initializations fail, a fatal error is issued and the function does
- not return. On return, the first thread and interpreter state have
- been created.
-
- Locking: you must hold the interpreter lock while calling this.
- (If the lock has not yet been initialized, that's equivalent to
- having the lock, but you cannot use multiple threads.)
-
-*/
-
+}
+
+/* Hack to force loading of object files */
+int (*_PyOS_mystrnicmp_hack)(const char *, const char *, Py_ssize_t) = \
+ PyOS_mystrnicmp; /* Python/pystrcmp.o */
+
+/* PyModule_GetWarningsModule is no longer necessary as of 2.6
+since _warnings is builtin. This API should not be used. */
+PyObject *
+PyModule_GetWarningsModule(void)
+{
+ return PyImport_ImportModule("warnings");
+}
+
+
+/* APIs to access the initialization flags
+ *
+ * Can be called prior to Py_Initialize.
+ */
+
+int
+_Py_IsCoreInitialized(void)
+{
+ return _PyRuntime.core_initialized;
+}
+
+int
+Py_IsInitialized(void)
+{
+ return _PyRuntime.initialized;
+}
+
+
+/* Global initializations. Can be undone by Py_FinalizeEx(). Don't
+ call this twice without an intervening Py_FinalizeEx() call. When
+ initializations fail, a fatal error is issued and the function does
+ not return. On return, the first thread and interpreter state have
+ been created.
+
+ Locking: you must hold the interpreter lock while calling this.
+ (If the lock has not yet been initialized, that's equivalent to
+ having the lock, but you cannot use multiple threads.)
+
+*/
+
static PyStatus
init_importlib(PyThreadState *tstate, PyObject *sysmod)
-{
- PyObject *importlib;
- PyObject *impmod;
- PyObject *value;
+{
+ PyObject *importlib;
+ PyObject *impmod;
+ PyObject *value;
PyInterpreterState *interp = tstate->interp;
int verbose = _PyInterpreterState_GetConfig(interp)->verbose;
-
- /* Import _importlib through its frozen version, _frozen_importlib. */
- if (PyImport_ImportFrozenModule("_frozen_importlib") <= 0) {
+
+ /* Import _importlib through its frozen version, _frozen_importlib. */
+ if (PyImport_ImportFrozenModule("_frozen_importlib") <= 0) {
return _PyStatus_ERR("can't import _frozen_importlib");
- }
+ }
else if (verbose) {
- PySys_FormatStderr("import _frozen_importlib # frozen\n");
- }
- importlib = PyImport_AddModule("_frozen_importlib");
- if (importlib == NULL) {
+ PySys_FormatStderr("import _frozen_importlib # frozen\n");
+ }
+ importlib = PyImport_AddModule("_frozen_importlib");
+ if (importlib == NULL) {
return _PyStatus_ERR("couldn't get _frozen_importlib from sys.modules");
- }
- interp->importlib = importlib;
- Py_INCREF(interp->importlib);
-
- interp->import_func = PyDict_GetItemString(interp->builtins, "__import__");
- if (interp->import_func == NULL)
+ }
+ interp->importlib = importlib;
+ Py_INCREF(interp->importlib);
+
+ interp->import_func = PyDict_GetItemString(interp->builtins, "__import__");
+ if (interp->import_func == NULL)
return _PyStatus_ERR("__import__ not found");
- Py_INCREF(interp->import_func);
-
- /* Import the _imp module */
- impmod = PyInit__imp();
- if (impmod == NULL) {
+ Py_INCREF(interp->import_func);
+
+ /* Import the _imp module */
+ impmod = PyInit__imp();
+ if (impmod == NULL) {
return _PyStatus_ERR("can't import _imp");
- }
+ }
else if (verbose) {
- PySys_FormatStderr("import _imp # builtin\n");
- }
- if (_PyImport_SetModuleString("_imp", impmod) < 0) {
+ PySys_FormatStderr("import _imp # builtin\n");
+ }
+ if (_PyImport_SetModuleString("_imp", impmod) < 0) {
return _PyStatus_ERR("can't save _imp to sys.modules");
- }
-
- /* Install importlib as the implementation of import */
- value = PyObject_CallMethod(importlib, "_install", "OO", sysmod, impmod);
- if (value == NULL) {
+ }
+
+ /* Install importlib as the implementation of import */
+ value = PyObject_CallMethod(importlib, "_install", "OO", sysmod, impmod);
+ if (value == NULL) {
_PyErr_Print(tstate);
return _PyStatus_ERR("importlib install failed");
- }
- Py_DECREF(value);
- Py_DECREF(impmod);
-
+ }
+ Py_DECREF(value);
+ Py_DECREF(impmod);
+
return _PyStatus_OK();
-}
-
+}
+
static PyStatus
init_importlib_external(PyThreadState *tstate)
-{
- PyObject *value;
+{
+ PyObject *value;
value = PyObject_CallMethod(tstate->interp->importlib,
- "_install_external_importers", "");
- if (value == NULL) {
+ "_install_external_importers", "");
+ if (value == NULL) {
_PyErr_Print(tstate);
return _PyStatus_ERR("external importer setup failed");
}
- Py_DECREF(value);
-
- value = PyImport_ImportModule("__res");
- if (value == NULL) {
- PyErr_Print();
+ Py_DECREF(value);
+
+ value = PyImport_ImportModule("__res");
+ if (value == NULL) {
+ PyErr_Print();
return _PyStatus_ERR("can't import __res");
- }
- Py_DECREF(value);
-
+ }
+ Py_DECREF(value);
+
return _PyImportZip_Init(tstate);
-}
-
-/* Helper functions to better handle the legacy C locale
- *
- * The legacy C locale assumes ASCII as the default text encoding, which
- * causes problems not only for the CPython runtime, but also other
- * components like GNU readline.
- *
- * Accordingly, when the CLI detects it, it attempts to coerce it to a
- * more capable UTF-8 based alternative as follows:
- *
- * if (_Py_LegacyLocaleDetected()) {
- * _Py_CoerceLegacyLocale();
- * }
- *
- * See the documentation of the PYTHONCOERCECLOCALE setting for more details.
- *
- * Locale coercion also impacts the default error handler for the standard
- * streams: while the usual default is "strict", the default for the legacy
- * C locale and for any of the coercion target locales is "surrogateescape".
- */
-
-int
+}
+
+/* Helper functions to better handle the legacy C locale
+ *
+ * The legacy C locale assumes ASCII as the default text encoding, which
+ * causes problems not only for the CPython runtime, but also other
+ * components like GNU readline.
+ *
+ * Accordingly, when the CLI detects it, it attempts to coerce it to a
+ * more capable UTF-8 based alternative as follows:
+ *
+ * if (_Py_LegacyLocaleDetected()) {
+ * _Py_CoerceLegacyLocale();
+ * }
+ *
+ * See the documentation of the PYTHONCOERCECLOCALE setting for more details.
+ *
+ * Locale coercion also impacts the default error handler for the standard
+ * streams: while the usual default is "strict", the default for the legacy
+ * C locale and for any of the coercion target locales is "surrogateescape".
+ */
+
+int
_Py_LegacyLocaleDetected(int warn)
-{
-#ifndef MS_WINDOWS
+{
+#ifndef MS_WINDOWS
if (!warn) {
const char *locale_override = getenv("LC_ALL");
if (locale_override != NULL && *locale_override != '\0') {
@@ -245,286 +245,286 @@ _Py_LegacyLocaleDetected(int warn)
}
}
- /* On non-Windows systems, the C locale is considered a legacy locale */
- /* XXX (ncoghlan): some platforms (notably Mac OS X) don't appear to treat
- * the POSIX locale as a simple alias for the C locale, so
- * we may also want to check for that explicitly.
- */
- const char *ctype_loc = setlocale(LC_CTYPE, NULL);
- return ctype_loc != NULL && strcmp(ctype_loc, "C") == 0;
-#else
- /* Windows uses code pages instead of locales, so no locale is legacy */
- return 0;
-#endif
-}
-
+ /* On non-Windows systems, the C locale is considered a legacy locale */
+ /* XXX (ncoghlan): some platforms (notably Mac OS X) don't appear to treat
+ * the POSIX locale as a simple alias for the C locale, so
+ * we may also want to check for that explicitly.
+ */
+ const char *ctype_loc = setlocale(LC_CTYPE, NULL);
+ return ctype_loc != NULL && strcmp(ctype_loc, "C") == 0;
+#else
+ /* Windows uses code pages instead of locales, so no locale is legacy */
+ return 0;
+#endif
+}
+
#ifndef MS_WINDOWS
-static const char *_C_LOCALE_WARNING =
- "Python runtime initialized with LC_CTYPE=C (a locale with default ASCII "
- "encoding), which may cause Unicode compatibility problems. Using C.UTF-8, "
- "C.utf8, or UTF-8 (if available) as alternative Unicode-compatible "
- "locales is recommended.\n";
-
-static void
+static const char *_C_LOCALE_WARNING =
+ "Python runtime initialized with LC_CTYPE=C (a locale with default ASCII "
+ "encoding), which may cause Unicode compatibility problems. Using C.UTF-8, "
+ "C.utf8, or UTF-8 (if available) as alternative Unicode-compatible "
+ "locales is recommended.\n";
+
+static void
emit_stderr_warning_for_legacy_locale(_PyRuntimeState *runtime)
-{
+{
const PyPreConfig *preconfig = &runtime->preconfig;
if (preconfig->coerce_c_locale_warn && _Py_LegacyLocaleDetected(1)) {
PySys_FormatStderr("%s", _C_LOCALE_WARNING);
- }
-}
+ }
+}
#endif /* !defined(MS_WINDOWS) */
-
-typedef struct _CandidateLocale {
- const char *locale_name; /* The locale to try as a coercion target */
-} _LocaleCoercionTarget;
-
-static _LocaleCoercionTarget _TARGET_LOCALES[] = {
- {"C.UTF-8"},
- {"C.utf8"},
- {"UTF-8"},
- {NULL}
-};
-
+
+typedef struct _CandidateLocale {
+ const char *locale_name; /* The locale to try as a coercion target */
+} _LocaleCoercionTarget;
+
+static _LocaleCoercionTarget _TARGET_LOCALES[] = {
+ {"C.UTF-8"},
+ {"C.utf8"},
+ {"UTF-8"},
+ {NULL}
+};
+
int
_Py_IsLocaleCoercionTarget(const char *ctype_loc)
-{
+{
const _LocaleCoercionTarget *target = NULL;
for (target = _TARGET_LOCALES; target->locale_name; target++) {
if (strcmp(ctype_loc, target->locale_name) == 0) {
return 1;
- }
+ }
}
return 0;
}
-
-
-#ifdef PY_COERCE_C_LOCALE
-static const char C_LOCALE_COERCION_WARNING[] =
- "Python detected LC_CTYPE=C: LC_CTYPE coerced to %.20s (set another locale "
- "or PYTHONCOERCECLOCALE=0 to disable this locale coercion behavior).\n";
-
+
+
+#ifdef PY_COERCE_C_LOCALE
+static const char C_LOCALE_COERCION_WARNING[] =
+ "Python detected LC_CTYPE=C: LC_CTYPE coerced to %.20s (set another locale "
+ "or PYTHONCOERCECLOCALE=0 to disable this locale coercion behavior).\n";
+
static int
_coerce_default_locale_settings(int warn, const _LocaleCoercionTarget *target)
-{
- const char *newloc = target->locale_name;
-
- /* Reset locale back to currently configured defaults */
- _Py_SetLocaleFromEnv(LC_ALL);
-
- /* Set the relevant locale environment variable */
- if (setenv("LC_CTYPE", newloc, 1)) {
- fprintf(stderr,
- "Error setting LC_CTYPE, skipping C locale coercion\n");
+{
+ const char *newloc = target->locale_name;
+
+ /* Reset locale back to currently configured defaults */
+ _Py_SetLocaleFromEnv(LC_ALL);
+
+ /* Set the relevant locale environment variable */
+ if (setenv("LC_CTYPE", newloc, 1)) {
+ fprintf(stderr,
+ "Error setting LC_CTYPE, skipping C locale coercion\n");
return 0;
- }
+ }
if (warn) {
- fprintf(stderr, C_LOCALE_COERCION_WARNING, newloc);
- }
-
- /* Reconfigure with the overridden environment variables */
- _Py_SetLocaleFromEnv(LC_ALL);
+ fprintf(stderr, C_LOCALE_COERCION_WARNING, newloc);
+ }
+
+ /* Reconfigure with the overridden environment variables */
+ _Py_SetLocaleFromEnv(LC_ALL);
return 1;
-}
-#endif
-
+}
+#endif
+
int
_Py_CoerceLegacyLocale(int warn)
-{
+{
int coerced = 0;
-#ifdef PY_COERCE_C_LOCALE
- char *oldloc = NULL;
-
- oldloc = _PyMem_RawStrdup(setlocale(LC_CTYPE, NULL));
- if (oldloc == NULL) {
+#ifdef PY_COERCE_C_LOCALE
+ char *oldloc = NULL;
+
+ oldloc = _PyMem_RawStrdup(setlocale(LC_CTYPE, NULL));
+ if (oldloc == NULL) {
return coerced;
- }
-
- const char *locale_override = getenv("LC_ALL");
- if (locale_override == NULL || *locale_override == '\0') {
- /* LC_ALL is also not set (or is set to an empty string) */
- const _LocaleCoercionTarget *target = NULL;
- for (target = _TARGET_LOCALES; target->locale_name; target++) {
- const char *new_locale = setlocale(LC_CTYPE,
- target->locale_name);
- if (new_locale != NULL) {
+ }
+
+ const char *locale_override = getenv("LC_ALL");
+ if (locale_override == NULL || *locale_override == '\0') {
+ /* LC_ALL is also not set (or is set to an empty string) */
+ const _LocaleCoercionTarget *target = NULL;
+ for (target = _TARGET_LOCALES; target->locale_name; target++) {
+ const char *new_locale = setlocale(LC_CTYPE,
+ target->locale_name);
+ if (new_locale != NULL) {
#if !defined(_Py_FORCE_UTF8_LOCALE) && defined(HAVE_LANGINFO_H) && defined(CODESET)
- /* Also ensure that nl_langinfo works in this locale */
- char *codeset = nl_langinfo(CODESET);
- if (!codeset || *codeset == '\0') {
- /* CODESET is not set or empty, so skip coercion */
- new_locale = NULL;
- _Py_SetLocaleFromEnv(LC_CTYPE);
- continue;
- }
-#endif
- /* Successfully configured locale, so make it the default */
+ /* Also ensure that nl_langinfo works in this locale */
+ char *codeset = nl_langinfo(CODESET);
+ if (!codeset || *codeset == '\0') {
+ /* CODESET is not set or empty, so skip coercion */
+ new_locale = NULL;
+ _Py_SetLocaleFromEnv(LC_CTYPE);
+ continue;
+ }
+#endif
+ /* Successfully configured locale, so make it the default */
coerced = _coerce_default_locale_settings(warn, target);
- goto done;
- }
- }
- }
- /* No C locale warning here, as Py_Initialize will emit one later */
-
- setlocale(LC_CTYPE, oldloc);
-
-done:
- PyMem_RawFree(oldloc);
-#endif
+ goto done;
+ }
+ }
+ }
+ /* No C locale warning here, as Py_Initialize will emit one later */
+
+ setlocale(LC_CTYPE, oldloc);
+
+done:
+ PyMem_RawFree(oldloc);
+#endif
return coerced;
-}
-
-/* _Py_SetLocaleFromEnv() is a wrapper around setlocale(category, "") to
- * isolate the idiosyncrasies of different libc implementations. It reads the
- * appropriate environment variable and uses its value to select the locale for
- * 'category'. */
-char *
-_Py_SetLocaleFromEnv(int category)
-{
- char *res;
-#ifdef __ANDROID__
- const char *locale;
- const char **pvar;
-#ifdef PY_COERCE_C_LOCALE
- const char *coerce_c_locale;
-#endif
- const char *utf8_locale = "C.UTF-8";
- const char *env_var_set[] = {
- "LC_ALL",
- "LC_CTYPE",
- "LANG",
- NULL,
- };
-
- /* Android setlocale(category, "") doesn't check the environment variables
- * and incorrectly sets the "C" locale at API 24 and older APIs. We only
- * check the environment variables listed in env_var_set. */
- for (pvar=env_var_set; *pvar; pvar++) {
- locale = getenv(*pvar);
- if (locale != NULL && *locale != '\0') {
- if (strcmp(locale, utf8_locale) == 0 ||
- strcmp(locale, "en_US.UTF-8") == 0) {
- return setlocale(category, utf8_locale);
- }
- return setlocale(category, "C");
- }
- }
-
- /* Android uses UTF-8, so explicitly set the locale to C.UTF-8 if none of
- * LC_ALL, LC_CTYPE, or LANG is set to a non-empty string.
- * Quote from POSIX section "8.2 Internationalization Variables":
- * "4. If the LANG environment variable is not set or is set to the empty
- * string, the implementation-defined default locale shall be used." */
-
-#ifdef PY_COERCE_C_LOCALE
- coerce_c_locale = getenv("PYTHONCOERCECLOCALE");
- if (coerce_c_locale == NULL || strcmp(coerce_c_locale, "0") != 0) {
- /* Some other ported code may check the environment variables (e.g. in
- * extension modules), so we make sure that they match the locale
- * configuration */
- if (setenv("LC_CTYPE", utf8_locale, 1)) {
- fprintf(stderr, "Warning: failed setting the LC_CTYPE "
- "environment variable to %s\n", utf8_locale);
- }
- }
-#endif
- res = setlocale(category, utf8_locale);
-#else /* !defined(__ANDROID__) */
- res = setlocale(category, "");
-#endif
- _Py_ResetForceASCII();
- return res;
-}
-
-
-/* Global initializations. Can be undone by Py_Finalize(). Don't
- call this twice without an intervening Py_Finalize() call.
-
+}
+
+/* _Py_SetLocaleFromEnv() is a wrapper around setlocale(category, "") to
+ * isolate the idiosyncrasies of different libc implementations. It reads the
+ * appropriate environment variable and uses its value to select the locale for
+ * 'category'. */
+char *
+_Py_SetLocaleFromEnv(int category)
+{
+ char *res;
+#ifdef __ANDROID__
+ const char *locale;
+ const char **pvar;
+#ifdef PY_COERCE_C_LOCALE
+ const char *coerce_c_locale;
+#endif
+ const char *utf8_locale = "C.UTF-8";
+ const char *env_var_set[] = {
+ "LC_ALL",
+ "LC_CTYPE",
+ "LANG",
+ NULL,
+ };
+
+ /* Android setlocale(category, "") doesn't check the environment variables
+ * and incorrectly sets the "C" locale at API 24 and older APIs. We only
+ * check the environment variables listed in env_var_set. */
+ for (pvar=env_var_set; *pvar; pvar++) {
+ locale = getenv(*pvar);
+ if (locale != NULL && *locale != '\0') {
+ if (strcmp(locale, utf8_locale) == 0 ||
+ strcmp(locale, "en_US.UTF-8") == 0) {
+ return setlocale(category, utf8_locale);
+ }
+ return setlocale(category, "C");
+ }
+ }
+
+ /* Android uses UTF-8, so explicitly set the locale to C.UTF-8 if none of
+ * LC_ALL, LC_CTYPE, or LANG is set to a non-empty string.
+ * Quote from POSIX section "8.2 Internationalization Variables":
+ * "4. If the LANG environment variable is not set or is set to the empty
+ * string, the implementation-defined default locale shall be used." */
+
+#ifdef PY_COERCE_C_LOCALE
+ coerce_c_locale = getenv("PYTHONCOERCECLOCALE");
+ if (coerce_c_locale == NULL || strcmp(coerce_c_locale, "0") != 0) {
+ /* Some other ported code may check the environment variables (e.g. in
+ * extension modules), so we make sure that they match the locale
+ * configuration */
+ if (setenv("LC_CTYPE", utf8_locale, 1)) {
+ fprintf(stderr, "Warning: failed setting the LC_CTYPE "
+ "environment variable to %s\n", utf8_locale);
+ }
+ }
+#endif
+ res = setlocale(category, utf8_locale);
+#else /* !defined(__ANDROID__) */
+ res = setlocale(category, "");
+#endif
+ _Py_ResetForceASCII();
+ return res;
+}
+
+
+/* Global initializations. Can be undone by Py_Finalize(). Don't
+ call this twice without an intervening Py_Finalize() call.
+
Every call to Py_InitializeFromConfig, Py_Initialize or Py_InitializeEx
- must have a corresponding call to Py_Finalize.
-
- Locking: you must hold the interpreter lock while calling these APIs.
- (If the lock has not yet been initialized, that's equivalent to
- having the lock, but you cannot use multiple threads.)
-
-*/
-
+ must have a corresponding call to Py_Finalize.
+
+ Locking: you must hold the interpreter lock while calling these APIs.
+ (If the lock has not yet been initialized, that's equivalent to
+ having the lock, but you cannot use multiple threads.)
+
+*/
+
static PyStatus
pyinit_core_reconfigure(_PyRuntimeState *runtime,
PyThreadState **tstate_p,
const PyConfig *config)
-{
+{
PyStatus status;
PyThreadState *tstate = _PyThreadState_GET();
if (!tstate) {
return _PyStatus_ERR("failed to read thread state");
- }
+ }
*tstate_p = tstate;
-
+
PyInterpreterState *interp = tstate->interp;
if (interp == NULL) {
return _PyStatus_ERR("can't make main interpreter");
- }
-
+ }
+
status = _PyConfig_Write(config, runtime);
if (_PyStatus_EXCEPTION(status)) {
return status;
}
-
+
status = _PyInterpreterState_SetConfig(interp, config);
if (_PyStatus_EXCEPTION(status)) {
return status;
}
config = _PyInterpreterState_GetConfig(interp);
-
+
if (config->_install_importlib) {
status = _PyConfig_WritePathConfig(config);
if (_PyStatus_EXCEPTION(status)) {
return status;
- }
- }
+ }
+ }
return _PyStatus_OK();
}
-
-
+
+
static PyStatus
pycore_init_runtime(_PyRuntimeState *runtime,
const PyConfig *config)
{
if (runtime->initialized) {
return _PyStatus_ERR("main interpreter already initialized");
- }
-
+ }
+
PyStatus status = _PyConfig_Write(config, runtime);
if (_PyStatus_EXCEPTION(status)) {
return status;
}
-
- /* Py_Finalize leaves _Py_Finalizing set in order to help daemon
- * threads behave a little more gracefully at interpreter shutdown.
- * We clobber it here so the new interpreter can start with a clean
- * slate.
- *
- * However, this may still lead to misbehaviour if there are daemon
- * threads still hanging around from a previous Py_Initialize/Finalize
- * pair :(
- */
+
+ /* Py_Finalize leaves _Py_Finalizing set in order to help daemon
+ * threads behave a little more gracefully at interpreter shutdown.
+ * We clobber it here so the new interpreter can start with a clean
+ * slate.
+ *
+ * However, this may still lead to misbehaviour if there are daemon
+ * threads still hanging around from a previous Py_Initialize/Finalize
+ * pair :(
+ */
_PyRuntimeState_SetFinalizing(runtime, NULL);
-
+
status = _Py_HashRandomization_Init(config);
if (_PyStatus_EXCEPTION(status)) {
return status;
- }
-
+ }
+
status = _PyInterpreterState_Enable(runtime);
if (_PyStatus_EXCEPTION(status)) {
return status;
- }
+ }
return _PyStatus_OK();
}
-
-
+
+
static PyStatus
init_interp_create_gil(PyThreadState *tstate)
{
@@ -556,54 +556,54 @@ pycore_create_interpreter(_PyRuntimeState *runtime,
PyThreadState **tstate_p)
{
PyInterpreterState *interp = PyInterpreterState_New();
- if (interp == NULL) {
+ if (interp == NULL) {
return _PyStatus_ERR("can't make main interpreter");
- }
-
+ }
+
PyStatus status = _PyInterpreterState_SetConfig(interp, config);
if (_PyStatus_EXCEPTION(status)) {
return status;
- }
-
- PyThreadState *tstate = PyThreadState_New(interp);
+ }
+
+ PyThreadState *tstate = PyThreadState_New(interp);
if (tstate == NULL) {
return _PyStatus_ERR("can't make first thread");
}
- (void) PyThreadState_Swap(tstate);
-
+ (void) PyThreadState_Swap(tstate);
+
status = init_interp_create_gil(tstate);
if (_PyStatus_EXCEPTION(status)) {
return status;
}
-
+
*tstate_p = tstate;
return _PyStatus_OK();
}
-
-
+
+
static PyStatus
pycore_init_types(PyThreadState *tstate)
{
PyStatus status;
int is_main_interp = _Py_IsMainInterpreter(tstate);
-
+
status = _PyGC_Init(tstate);
if (_PyStatus_EXCEPTION(status)) {
return status;
}
-
+
if (is_main_interp) {
status = _PyTypes_Init();
if (_PyStatus_EXCEPTION(status)) {
return status;
}
}
-
+
if (!_PyLong_Init(tstate)) {
return _PyStatus_ERR("can't init longs");
}
-
+
if (is_main_interp) {
status = _PyUnicode_Init();
if (_PyStatus_EXCEPTION(status)) {
@@ -614,23 +614,23 @@ pycore_init_types(PyThreadState *tstate)
status = _PyExc_Init();
if (_PyStatus_EXCEPTION(status)) {
return status;
- }
-
+ }
+
if (is_main_interp) {
if (!_PyFloat_Init()) {
return _PyStatus_ERR("can't init float");
}
-
+
if (_PyStructSequence_Init() < 0) {
return _PyStatus_ERR("can't initialize structseq");
}
}
-
+
status = _PyErr_Init();
if (_PyStatus_EXCEPTION(status)) {
return status;
}
-
+
if (is_main_interp) {
if (!_PyContext_Init()) {
return _PyStatus_ERR("can't init context");
@@ -639,7 +639,7 @@ pycore_init_types(PyThreadState *tstate)
return _PyStatus_OK();
}
-
+
static PyStatus
pycore_init_builtins(PyThreadState *tstate)
@@ -655,7 +655,7 @@ pycore_init_builtins(PyThreadState *tstate)
if (_PyImport_FixupBuiltin(bimod, "builtins", interp->modules) < 0) {
goto error;
}
-
+
PyObject *builtins_dict = PyModule_GetDict(bimod);
if (builtins_dict == NULL) {
goto error;
@@ -682,8 +682,8 @@ error:
Py_XDECREF(bimod);
return _PyStatus_ERR("can't initialize builtins module");
}
-
-
+
+
static PyStatus
pycore_init_import_warnings(PyThreadState *tstate, PyObject *sysmod)
{
@@ -692,8 +692,8 @@ pycore_init_import_warnings(PyThreadState *tstate, PyObject *sysmod)
PyStatus status = _PyImportHooks_Init(tstate);
if (_PyStatus_EXCEPTION(status)) {
return status;
- }
-
+ }
+
const PyConfig *config = _PyInterpreterState_GetConfig(tstate->interp);
if (_Py_IsMainInterpreter(tstate)) {
/* Initialize _warnings. */
@@ -709,20 +709,20 @@ pycore_init_import_warnings(PyThreadState *tstate, PyObject *sysmod)
}
}
}
-
- /* This call sets up builtin and frozen import support */
+
+ /* This call sets up builtin and frozen import support */
if (config->_install_importlib) {
status = init_importlib(tstate, sysmod);
if (_PyStatus_EXCEPTION(status)) {
return status;
- }
- }
+ }
+ }
assert(!_PyErr_Occurred(tstate));
return _PyStatus_OK();
}
-
+
static PyStatus
pycore_interp_init(PyThreadState *tstate)
@@ -776,32 +776,32 @@ pyinit_config(_PyRuntimeState *runtime,
return status;
}
- /* Only when we get here is the runtime core fully initialized */
+ /* Only when we get here is the runtime core fully initialized */
runtime->core_initialized = 1;
return _PyStatus_OK();
-}
-
-
+}
+
+
PyStatus
_Py_PreInitializeFromPyArgv(const PyPreConfig *src_config, const _PyArgv *args)
-{
+{
PyStatus status;
-
+
if (src_config == NULL) {
return _PyStatus_ERR("preinitialization config is NULL");
}
-
+
status = _PyRuntime_Initialize();
if (_PyStatus_EXCEPTION(status)) {
return status;
}
_PyRuntimeState *runtime = &_PyRuntime;
-
+
if (runtime->preinitialized) {
/* If it's already configured: ignored the new configuration */
return _PyStatus_OK();
}
-
+
/* Note: preinitialized remains 1 on error, it is only set to 0
at exit on success. */
runtime->preinitializing = 1;
@@ -811,7 +811,7 @@ _Py_PreInitializeFromPyArgv(const PyPreConfig *src_config, const _PyArgv *args)
status = _PyPreConfig_InitFromPreConfig(&config, src_config);
if (_PyStatus_EXCEPTION(status)) {
return status;
- }
+ }
status = _PyPreConfig_Read(&config, args);
if (_PyStatus_EXCEPTION(status)) {
@@ -883,11 +883,11 @@ _Py_PreInitializeFromConfig(const PyConfig *config,
.wchar_argv = config->argv.items};
return _Py_PreInitializeFromPyArgv(&preconfig, &config_args);
}
- else {
+ else {
return _Py_PreInitializeFromPyArgv(&preconfig, args);
- }
+ }
}
-
+
/* Begin interpreter initialization
*
@@ -923,14 +923,14 @@ pyinit_core(_PyRuntimeState *runtime,
status = _PyConfig_Copy(&config, src_config);
if (_PyStatus_EXCEPTION(status)) {
- goto done;
- }
-
+ goto done;
+ }
+
status = PyConfig_Read(&config);
if (_PyStatus_EXCEPTION(status)) {
goto done;
}
-
+
if (!runtime->core_initialized) {
status = pyinit_config(runtime, tstate_p, &config);
}
@@ -941,24 +941,24 @@ pyinit_core(_PyRuntimeState *runtime,
goto done;
}
-done:
+done:
PyConfig_Clear(&config);
return status;
-}
+}
+
-
-/* Py_Initialize() has already been called: update the main interpreter
- configuration. Example of bpo-34008: Py_Main() called after
- Py_Initialize(). */
+/* Py_Initialize() has already been called: update the main interpreter
+ configuration. Example of bpo-34008: Py_Main() called after
+ Py_Initialize(). */
static PyStatus
_Py_ReconfigureMainInterpreter(PyThreadState *tstate)
-{
+{
const PyConfig *config = _PyInterpreterState_GetConfig(tstate->interp);
PyObject *argv = _PyWideStringList_AsList(&config->argv);
if (argv == NULL) {
return _PyStatus_NO_MEMORY(); \
- }
+ }
int res = PyDict_SetItemString(tstate->interp->sysdict, "argv", argv);
Py_DECREF(argv);
@@ -966,59 +966,59 @@ _Py_ReconfigureMainInterpreter(PyThreadState *tstate)
return _PyStatus_ERR("fail to set sys.argv");
}
return _PyStatus_OK();
-}
-
+}
+
static PyStatus
init_interp_main(PyThreadState *tstate)
-{
+{
assert(!_PyErr_Occurred(tstate));
-
+
PyStatus status;
int is_main_interp = _Py_IsMainInterpreter(tstate);
PyInterpreterState *interp = tstate->interp;
const PyConfig *config = _PyInterpreterState_GetConfig(interp);
-
+
if (!config->_install_importlib) {
- /* Special mode for freeze_importlib: run with no import system
- *
- * This means anything which needs support from extension modules
- * or pure Python code in the standard library won't work.
- */
+ /* Special mode for freeze_importlib: run with no import system
+ *
+ * This means anything which needs support from extension modules
+ * or pure Python code in the standard library won't work.
+ */
if (is_main_interp) {
interp->runtime->initialized = 1;
}
return _PyStatus_OK();
- }
-
+ }
+
if (is_main_interp) {
if (_PyTime_Init() < 0) {
return _PyStatus_ERR("can't initialize time");
}
- }
-
+ }
+
if (_PySys_InitMain(tstate) < 0) {
return _PyStatus_ERR("can't finish initializing sys");
- }
-
+ }
+
status = init_importlib_external(tstate);
if (_PyStatus_EXCEPTION(status)) {
return status;
- }
-
+ }
+
if (is_main_interp) {
/* initialize the faulthandler module */
status = _PyFaulthandler_Init(config->faulthandler);
if (_PyStatus_EXCEPTION(status)) {
return status;
}
- }
-
+ }
+
status = _PyUnicode_InitEncodings(tstate);
if (_PyStatus_EXCEPTION(status)) {
return status;
- }
-
+ }
+
if (is_main_interp) {
if (_PySignal_Init(config->install_signal_handlers) < 0) {
return _PyStatus_ERR("can't initialize signals");
@@ -1027,23 +1027,23 @@ init_interp_main(PyThreadState *tstate)
if (_PyTraceMalloc_Init(config->tracemalloc) < 0) {
return _PyStatus_ERR("can't initialize tracemalloc");
}
- }
-
+ }
+
status = init_sys_streams(tstate);
if (_PyStatus_EXCEPTION(status)) {
return status;
}
-
+
status = init_set_builtins_open();
if (_PyStatus_EXCEPTION(status)) {
return status;
- }
-
+ }
+
status = add_main_module(interp);
if (_PyStatus_EXCEPTION(status)) {
return status;
- }
-
+ }
+
if (is_main_interp) {
/* Initialize warnings. */
PyObject *warnoptions = PySys_GetObject("warnoptions");
@@ -1055,17 +1055,17 @@ init_interp_main(PyThreadState *tstate)
_PyErr_Print(tstate);
}
Py_XDECREF(warnings_module);
- }
+ }
interp->runtime->initialized = 1;
- }
-
+ }
+
if (config->site_import) {
status = init_import_site();
if (_PyStatus_EXCEPTION(status)) {
return status;
- }
- }
+ }
+ }
if (is_main_interp) {
#ifndef MS_WINDOWS
@@ -1076,9 +1076,9 @@ init_interp_main(PyThreadState *tstate)
assert(!_PyErr_Occurred(tstate));
return _PyStatus_OK();
-}
-
-
+}
+
+
/* Update interpreter state based on supplied configuration settings
*
* After calling this function, most of the restrictions on the interpreter
@@ -1125,24 +1125,24 @@ _Py_InitializeMain(void)
PyStatus
Py_InitializeFromConfig(const PyConfig *config)
-{
+{
if (config == NULL) {
return _PyStatus_ERR("initialization config is NULL");
}
-
+
PyStatus status;
status = _PyRuntime_Initialize();
if (_PyStatus_EXCEPTION(status)) {
return status;
- }
+ }
_PyRuntimeState *runtime = &_PyRuntime;
-
+
PyThreadState *tstate = NULL;
status = pyinit_core(runtime, config, &tstate);
if (_PyStatus_EXCEPTION(status)) {
return status;
- }
+ }
config = _PyInterpreterState_GetConfig(tstate->interp);
if (config->_init_main) {
@@ -1150,15 +1150,15 @@ Py_InitializeFromConfig(const PyConfig *config)
if (_PyStatus_EXCEPTION(status)) {
return status;
}
- }
-
+ }
+
return _PyStatus_OK();
-}
-
-
-void
-Py_InitializeEx(int install_sigs)
-{
+}
+
+
+void
+Py_InitializeEx(int install_sigs)
+{
PyStatus status;
status = _PyRuntime_Initialize();
@@ -1168,91 +1168,91 @@ Py_InitializeEx(int install_sigs)
_PyRuntimeState *runtime = &_PyRuntime;
if (runtime->initialized) {
- /* bpo-33932: Calling Py_Initialize() twice does nothing. */
- return;
- }
-
+ /* bpo-33932: Calling Py_Initialize() twice does nothing. */
+ return;
+ }
+
PyConfig config;
_PyConfig_InitCompatConfig(&config);
- config.install_signal_handlers = install_sigs;
-
+ config.install_signal_handlers = install_sigs;
+
status = Py_InitializeFromConfig(&config);
if (_PyStatus_EXCEPTION(status)) {
Py_ExitStatusException(status);
- }
-}
-
-void
-Py_Initialize(void)
-{
- Py_InitializeEx(1);
-}
-
-
-/* Flush stdout and stderr */
-
-static int
-file_is_closed(PyObject *fobj)
-{
- int r;
- PyObject *tmp = PyObject_GetAttrString(fobj, "closed");
- if (tmp == NULL) {
- PyErr_Clear();
- return 0;
- }
- r = PyObject_IsTrue(tmp);
- Py_DECREF(tmp);
- if (r < 0)
- PyErr_Clear();
- return r > 0;
-}
-
-static int
-flush_std_files(void)
-{
- PyObject *fout = _PySys_GetObjectId(&PyId_stdout);
- PyObject *ferr = _PySys_GetObjectId(&PyId_stderr);
- PyObject *tmp;
- int status = 0;
-
- if (fout != NULL && fout != Py_None && !file_is_closed(fout)) {
+ }
+}
+
+void
+Py_Initialize(void)
+{
+ Py_InitializeEx(1);
+}
+
+
+/* Flush stdout and stderr */
+
+static int
+file_is_closed(PyObject *fobj)
+{
+ int r;
+ PyObject *tmp = PyObject_GetAttrString(fobj, "closed");
+ if (tmp == NULL) {
+ PyErr_Clear();
+ return 0;
+ }
+ r = PyObject_IsTrue(tmp);
+ Py_DECREF(tmp);
+ if (r < 0)
+ PyErr_Clear();
+ return r > 0;
+}
+
+static int
+flush_std_files(void)
+{
+ PyObject *fout = _PySys_GetObjectId(&PyId_stdout);
+ PyObject *ferr = _PySys_GetObjectId(&PyId_stderr);
+ PyObject *tmp;
+ int status = 0;
+
+ if (fout != NULL && fout != Py_None && !file_is_closed(fout)) {
tmp = _PyObject_CallMethodIdNoArgs(fout, &PyId_flush);
- if (tmp == NULL) {
- PyErr_WriteUnraisable(fout);
- status = -1;
- }
- else
- Py_DECREF(tmp);
- }
-
- if (ferr != NULL && ferr != Py_None && !file_is_closed(ferr)) {
+ if (tmp == NULL) {
+ PyErr_WriteUnraisable(fout);
+ status = -1;
+ }
+ else
+ Py_DECREF(tmp);
+ }
+
+ if (ferr != NULL && ferr != Py_None && !file_is_closed(ferr)) {
tmp = _PyObject_CallMethodIdNoArgs(ferr, &PyId_flush);
- if (tmp == NULL) {
- PyErr_Clear();
- status = -1;
- }
- else
- Py_DECREF(tmp);
- }
-
- return status;
-}
-
-/* Undo the effect of Py_Initialize().
-
- Beware: if multiple interpreter and/or thread states exist, these
- are not wiped out; only the current thread and interpreter state
- are deleted. But since everything else is deleted, those other
- interpreter and thread states should no longer be used.
-
- (XXX We should do better, e.g. wipe out all interpreters and
- threads.)
-
- Locking: as above.
-
-*/
-
+ if (tmp == NULL) {
+ PyErr_Clear();
+ status = -1;
+ }
+ else
+ Py_DECREF(tmp);
+ }
+
+ return status;
+}
+
+/* Undo the effect of Py_Initialize().
+
+ Beware: if multiple interpreter and/or thread states exist, these
+ are not wiped out; only the current thread and interpreter state
+ are deleted. But since everything else is deleted, those other
+ interpreter and thread states should no longer be used.
+
+ (XXX We should do better, e.g. wipe out all interpreters and
+ threads.)
+
+ Locking: as above.
+
+*/
+
static void
finalize_interp_types(PyThreadState *tstate, int is_main_interp)
@@ -1349,55 +1349,55 @@ finalize_interp_delete(PyThreadState *tstate)
}
-int
-Py_FinalizeEx(void)
-{
- int status = 0;
-
+int
+Py_FinalizeEx(void)
+{
+ int status = 0;
+
_PyRuntimeState *runtime = &_PyRuntime;
if (!runtime->initialized) {
- return status;
+ return status;
}
-
+
/* Get current thread state and interpreter pointer */
PyThreadState *tstate = _PyRuntimeState_GetThreadState(runtime);
// Wrap up existing "threading"-module-created, non-daemon threads.
wait_for_thread_shutdown(tstate);
-
+
// Make any remaining pending calls.
_Py_FinishPendingCalls(tstate);
- /* The interpreter is still entirely intact at this point, and the
- * exit funcs may be relying on that. In particular, if some thread
- * or exit func is still waiting to do an import, the import machinery
- * expects Py_IsInitialized() to return true. So don't say the
+ /* The interpreter is still entirely intact at this point, and the
+ * exit funcs may be relying on that. In particular, if some thread
+ * or exit func is still waiting to do an import, the import machinery
+ * expects Py_IsInitialized() to return true. So don't say the
* runtime is uninitialized until after the exit funcs have run.
- * Note that Threading.py uses an exit func to do a join on all the
- * threads created thru it, so this also protects pending imports in
- * the threads created via Threading.
- */
-
+ * Note that Threading.py uses an exit func to do a join on all the
+ * threads created thru it, so this also protects pending imports in
+ * the threads created via Threading.
+ */
+
call_py_exitfuncs(tstate);
-
- /* Copy the core config, PyInterpreterState_Delete() free
- the core config memory */
-#ifdef Py_REF_DEBUG
+
+ /* Copy the core config, PyInterpreterState_Delete() free
+ the core config memory */
+#ifdef Py_REF_DEBUG
int show_ref_count = tstate->interp->config.show_ref_count;
-#endif
-#ifdef Py_TRACE_REFS
+#endif
+#ifdef Py_TRACE_REFS
int dump_refs = tstate->interp->config.dump_refs;
-#endif
-#ifdef WITH_PYMALLOC
+#endif
+#ifdef WITH_PYMALLOC
int malloc_stats = tstate->interp->config.malloc_stats;
-#endif
-
+#endif
+
/* Remaining daemon threads will automatically exit
when they attempt to take the GIL (ex: PyEval_RestoreThread()). */
_PyRuntimeState_SetFinalizing(runtime, tstate);
runtime->initialized = 0;
runtime->core_initialized = 0;
-
+
/* Destroy the state of all threads of the interpreter, except of the
current thread. In practice, only daemon threads should still be alive,
except if wait_for_thread_shutdown() has been cancelled by CTRL+C.
@@ -1408,192 +1408,192 @@ Py_FinalizeEx(void)
immediately. */
_PyThreadState_DeleteExcept(runtime, tstate);
- /* Flush sys.stdout and sys.stderr */
- if (flush_std_files() < 0) {
- status = -1;
- }
-
- /* Disable signal handling */
- PyOS_FiniInterrupts();
-
- /* Collect garbage. This may call finalizers; it's nice to call these
- * before all modules are destroyed.
- * XXX If a __del__ or weakref callback is triggered here, and tries to
- * XXX import a module, bad things can happen, because Python no
- * XXX longer believes it's initialized.
- * XXX Fatal Python error: Interpreter not initialized (version mismatch?)
- * XXX is easy to provoke that way. I've also seen, e.g.,
- * XXX Exception exceptions.ImportError: 'No module named sha'
- * XXX in <function callback at 0x008F5718> ignored
- * XXX but I'm unclear on exactly how that one happens. In any case,
- * XXX I haven't seen a real-life report of either of these.
- */
- _PyGC_CollectIfEnabled();
-
- /* Destroy all modules */
+ /* Flush sys.stdout and sys.stderr */
+ if (flush_std_files() < 0) {
+ status = -1;
+ }
+
+ /* Disable signal handling */
+ PyOS_FiniInterrupts();
+
+ /* Collect garbage. This may call finalizers; it's nice to call these
+ * before all modules are destroyed.
+ * XXX If a __del__ or weakref callback is triggered here, and tries to
+ * XXX import a module, bad things can happen, because Python no
+ * XXX longer believes it's initialized.
+ * XXX Fatal Python error: Interpreter not initialized (version mismatch?)
+ * XXX is easy to provoke that way. I've also seen, e.g.,
+ * XXX Exception exceptions.ImportError: 'No module named sha'
+ * XXX in <function callback at 0x008F5718> ignored
+ * XXX but I'm unclear on exactly how that one happens. In any case,
+ * XXX I haven't seen a real-life report of either of these.
+ */
+ _PyGC_CollectIfEnabled();
+
+ /* Destroy all modules */
_PyImport_Cleanup(tstate);
-
+
/* Print debug stats if any */
_PyEval_Fini();
- /* Flush sys.stdout and sys.stderr (again, in case more was printed) */
- if (flush_std_files() < 0) {
- status = -1;
- }
-
- /* Collect final garbage. This disposes of cycles created by
- * class definitions, for example.
- * XXX This is disabled because it caused too many problems. If
- * XXX a __del__ or weakref callback triggers here, Python code has
- * XXX a hard time running, because even the sys module has been
- * XXX cleared out (sys.stdout is gone, sys.excepthook is gone, etc).
- * XXX One symptom is a sequence of information-free messages
- * XXX coming from threads (if a __del__ or callback is invoked,
- * XXX other threads can execute too, and any exception they encounter
- * XXX triggers a comedy of errors as subsystem after subsystem
- * XXX fails to find what it *expects* to find in sys to help report
- * XXX the exception and consequent unexpected failures). I've also
- * XXX seen segfaults then, after adding print statements to the
- * XXX Python code getting called.
- */
-#if 0
- _PyGC_CollectIfEnabled();
-#endif
-
- /* Disable tracemalloc after all Python objects have been destroyed,
- so it is possible to use tracemalloc in objects destructor. */
- _PyTraceMalloc_Fini();
-
- /* Destroy the database used by _PyImport_{Fixup,Find}Extension */
- _PyImport_Fini();
-
- /* Cleanup typeobject.c's internal caches. */
- _PyType_Fini();
-
- /* unload faulthandler module */
- _PyFaulthandler_Fini();
-
- /* dump hash stats */
- _PyHash_Fini();
-
-#ifdef Py_REF_DEBUG
- if (show_ref_count) {
- _PyDebug_PrintTotalRefs();
- }
-#endif
-
-#ifdef Py_TRACE_REFS
- /* Display all objects still alive -- this can invoke arbitrary
- * __repr__ overrides, so requires a mostly-intact interpreter.
- * Alas, a lot of stuff may still be alive now that will be cleaned
- * up later.
- */
- if (dump_refs) {
- _Py_PrintReferences(stderr);
- }
-#endif /* Py_TRACE_REFS */
-
+ /* Flush sys.stdout and sys.stderr (again, in case more was printed) */
+ if (flush_std_files() < 0) {
+ status = -1;
+ }
+
+ /* Collect final garbage. This disposes of cycles created by
+ * class definitions, for example.
+ * XXX This is disabled because it caused too many problems. If
+ * XXX a __del__ or weakref callback triggers here, Python code has
+ * XXX a hard time running, because even the sys module has been
+ * XXX cleared out (sys.stdout is gone, sys.excepthook is gone, etc).
+ * XXX One symptom is a sequence of information-free messages
+ * XXX coming from threads (if a __del__ or callback is invoked,
+ * XXX other threads can execute too, and any exception they encounter
+ * XXX triggers a comedy of errors as subsystem after subsystem
+ * XXX fails to find what it *expects* to find in sys to help report
+ * XXX the exception and consequent unexpected failures). I've also
+ * XXX seen segfaults then, after adding print statements to the
+ * XXX Python code getting called.
+ */
+#if 0
+ _PyGC_CollectIfEnabled();
+#endif
+
+ /* Disable tracemalloc after all Python objects have been destroyed,
+ so it is possible to use tracemalloc in objects destructor. */
+ _PyTraceMalloc_Fini();
+
+ /* Destroy the database used by _PyImport_{Fixup,Find}Extension */
+ _PyImport_Fini();
+
+ /* Cleanup typeobject.c's internal caches. */
+ _PyType_Fini();
+
+ /* unload faulthandler module */
+ _PyFaulthandler_Fini();
+
+ /* dump hash stats */
+ _PyHash_Fini();
+
+#ifdef Py_REF_DEBUG
+ if (show_ref_count) {
+ _PyDebug_PrintTotalRefs();
+ }
+#endif
+
+#ifdef Py_TRACE_REFS
+ /* Display all objects still alive -- this can invoke arbitrary
+ * __repr__ overrides, so requires a mostly-intact interpreter.
+ * Alas, a lot of stuff may still be alive now that will be cleaned
+ * up later.
+ */
+ if (dump_refs) {
+ _Py_PrintReferences(stderr);
+ }
+#endif /* Py_TRACE_REFS */
+
finalize_interp_clear(tstate);
finalize_interp_delete(tstate);
-
-#ifdef Py_TRACE_REFS
- /* Display addresses (& refcnts) of all objects still alive.
- * An address can be used to find the repr of the object, printed
- * above by _Py_PrintReferences.
- */
- if (dump_refs) {
- _Py_PrintReferenceAddresses(stderr);
- }
-#endif /* Py_TRACE_REFS */
-#ifdef WITH_PYMALLOC
- if (malloc_stats) {
- _PyObject_DebugMallocStats(stderr);
- }
-#endif
-
+
+#ifdef Py_TRACE_REFS
+ /* Display addresses (& refcnts) of all objects still alive.
+ * An address can be used to find the repr of the object, printed
+ * above by _Py_PrintReferences.
+ */
+ if (dump_refs) {
+ _Py_PrintReferenceAddresses(stderr);
+ }
+#endif /* Py_TRACE_REFS */
+#ifdef WITH_PYMALLOC
+ if (malloc_stats) {
+ _PyObject_DebugMallocStats(stderr);
+ }
+#endif
+
call_ll_exitfuncs(runtime);
-
- _PyRuntime_Finalize();
- return status;
-}
-
-void
-Py_Finalize(void)
-{
- Py_FinalizeEx();
-}
-
-
-/* Create and initialize a new interpreter and thread, and return the
- new thread. This requires that Py_Initialize() has been called
- first.
-
- Unsuccessful initialization yields a NULL pointer. Note that *no*
- exception information is available even in this case -- the
- exception information is held in the thread, and there is no
- thread.
-
- Locking: as above.
-
-*/
-
+
+ _PyRuntime_Finalize();
+ return status;
+}
+
+void
+Py_Finalize(void)
+{
+ Py_FinalizeEx();
+}
+
+
+/* Create and initialize a new interpreter and thread, and return the
+ new thread. This requires that Py_Initialize() has been called
+ first.
+
+ Unsuccessful initialization yields a NULL pointer. Note that *no*
+ exception information is available even in this case -- the
+ exception information is held in the thread, and there is no
+ thread.
+
+ Locking: as above.
+
+*/
+
static PyStatus
new_interpreter(PyThreadState **tstate_p, int isolated_subinterpreter)
-{
+{
PyStatus status;
-
+
status = _PyRuntime_Initialize();
if (_PyStatus_EXCEPTION(status)) {
return status;
- }
+ }
_PyRuntimeState *runtime = &_PyRuntime;
-
+
if (!runtime->initialized) {
return _PyStatus_ERR("Py_Initialize must be called first");
}
- /* Issue #10915, #15751: The GIL API doesn't work with multiple
- interpreters: disable PyGILState_Check(). */
+ /* Issue #10915, #15751: The GIL API doesn't work with multiple
+ interpreters: disable PyGILState_Check(). */
runtime->gilstate.check_enabled = 0;
-
+
PyInterpreterState *interp = PyInterpreterState_New();
- if (interp == NULL) {
- *tstate_p = NULL;
+ if (interp == NULL) {
+ *tstate_p = NULL;
return _PyStatus_OK();
- }
-
+ }
+
PyThreadState *tstate = PyThreadState_New(interp);
- if (tstate == NULL) {
- PyInterpreterState_Delete(interp);
- *tstate_p = NULL;
+ if (tstate == NULL) {
+ PyInterpreterState_Delete(interp);
+ *tstate_p = NULL;
return _PyStatus_OK();
- }
-
+ }
+
PyThreadState *save_tstate = PyThreadState_Swap(tstate);
-
- /* Copy the current interpreter config into the new interpreter */
+
+ /* Copy the current interpreter config into the new interpreter */
const PyConfig *config;
- if (save_tstate != NULL) {
+ if (save_tstate != NULL) {
config = _PyInterpreterState_GetConfig(save_tstate->interp);
}
else
{
- /* No current thread state, copy from the main interpreter */
- PyInterpreterState *main_interp = PyInterpreterState_Main();
+ /* No current thread state, copy from the main interpreter */
+ PyInterpreterState *main_interp = PyInterpreterState_Main();
config = _PyInterpreterState_GetConfig(main_interp);
- }
-
+ }
+
status = _PyInterpreterState_SetConfig(interp, config);
if (_PyStatus_EXCEPTION(status)) {
goto error;
- }
+ }
interp->config._isolated_interpreter = isolated_subinterpreter;
status = init_interp_create_gil(tstate);
if (_PyStatus_EXCEPTION(status)) {
goto error;
- }
-
+ }
+
status = pycore_interp_init(tstate);
if (_PyStatus_EXCEPTION(status)) {
goto error;
@@ -1602,59 +1602,59 @@ new_interpreter(PyThreadState **tstate_p, int isolated_subinterpreter)
status = init_interp_main(tstate);
if (_PyStatus_EXCEPTION(status)) {
goto error;
- }
-
- *tstate_p = tstate;
+ }
+
+ *tstate_p = tstate;
return _PyStatus_OK();
-
+
error:
*tstate_p = NULL;
- /* Oops, it didn't work. Undo it all. */
- PyErr_PrintEx(0);
- PyThreadState_Clear(tstate);
- PyThreadState_Delete(tstate);
- PyInterpreterState_Delete(interp);
+ /* Oops, it didn't work. Undo it all. */
+ PyErr_PrintEx(0);
+ PyThreadState_Clear(tstate);
+ PyThreadState_Delete(tstate);
+ PyInterpreterState_Delete(interp);
PyThreadState_Swap(save_tstate);
-
+
return status;
-}
-
-PyThreadState *
+}
+
+PyThreadState *
_Py_NewInterpreter(int isolated_subinterpreter)
-{
+{
PyThreadState *tstate = NULL;
PyStatus status = new_interpreter(&tstate, isolated_subinterpreter);
if (_PyStatus_EXCEPTION(status)) {
Py_ExitStatusException(status);
- }
- return tstate;
-
-}
-
+ }
+ return tstate;
+
+}
+
PyThreadState *
Py_NewInterpreter(void)
{
return _Py_NewInterpreter(0);
}
-/* Delete an interpreter and its last thread. This requires that the
- given thread state is current, that the thread has no remaining
- frames, and that it is its interpreter's only remaining thread.
- It is a fatal error to violate these constraints.
-
- (Py_FinalizeEx() doesn't have these constraints -- it zaps
- everything, regardless.)
-
- Locking: as above.
-
-*/
-
-void
-Py_EndInterpreter(PyThreadState *tstate)
-{
- PyInterpreterState *interp = tstate->interp;
-
+/* Delete an interpreter and its last thread. This requires that the
+ given thread state is current, that the thread has no remaining
+ frames, and that it is its interpreter's only remaining thread.
+ It is a fatal error to violate these constraints.
+
+ (Py_FinalizeEx() doesn't have these constraints -- it zaps
+ everything, regardless.)
+
+ Locking: as above.
+
+*/
+
+void
+Py_EndInterpreter(PyThreadState *tstate)
+{
+ PyInterpreterState *interp = tstate->interp;
+
if (tstate != _PyThreadState_GET()) {
Py_FatalError("thread is not current");
}
@@ -1662,90 +1662,90 @@ Py_EndInterpreter(PyThreadState *tstate)
Py_FatalError("thread still has a frame");
}
interp->finalizing = 1;
-
+
// Wrap up existing "threading"-module-created, non-daemon threads.
wait_for_thread_shutdown(tstate);
-
+
call_py_exitfuncs(tstate);
-
+
if (tstate != interp->tstate_head || tstate->next != NULL) {
Py_FatalError("not the last thread");
}
-
+
_PyImport_Cleanup(tstate);
finalize_interp_clear(tstate);
finalize_interp_delete(tstate);
-}
-
-/* Add the __main__ module */
-
+}
+
+/* Add the __main__ module */
+
static PyStatus
-add_main_module(PyInterpreterState *interp)
-{
- PyObject *m, *d, *loader, *ann_dict;
- m = PyImport_AddModule("__main__");
- if (m == NULL)
+add_main_module(PyInterpreterState *interp)
+{
+ PyObject *m, *d, *loader, *ann_dict;
+ m = PyImport_AddModule("__main__");
+ if (m == NULL)
return _PyStatus_ERR("can't create __main__ module");
-
- d = PyModule_GetDict(m);
- ann_dict = PyDict_New();
- if ((ann_dict == NULL) ||
- (PyDict_SetItemString(d, "__annotations__", ann_dict) < 0)) {
+
+ d = PyModule_GetDict(m);
+ ann_dict = PyDict_New();
+ if ((ann_dict == NULL) ||
+ (PyDict_SetItemString(d, "__annotations__", ann_dict) < 0)) {
return _PyStatus_ERR("Failed to initialize __main__.__annotations__");
- }
- Py_DECREF(ann_dict);
-
- if (PyDict_GetItemString(d, "__builtins__") == NULL) {
- PyObject *bimod = PyImport_ImportModule("builtins");
- if (bimod == NULL) {
+ }
+ Py_DECREF(ann_dict);
+
+ if (PyDict_GetItemString(d, "__builtins__") == NULL) {
+ PyObject *bimod = PyImport_ImportModule("builtins");
+ if (bimod == NULL) {
return _PyStatus_ERR("Failed to retrieve builtins module");
- }
- if (PyDict_SetItemString(d, "__builtins__", bimod) < 0) {
+ }
+ if (PyDict_SetItemString(d, "__builtins__", bimod) < 0) {
return _PyStatus_ERR("Failed to initialize __main__.__builtins__");
- }
- Py_DECREF(bimod);
- }
-
- /* Main is a little special - imp.is_builtin("__main__") will return
- * False, but BuiltinImporter is still the most appropriate initial
- * setting for its __loader__ attribute. A more suitable value will
- * be set if __main__ gets further initialized later in the startup
- * process.
- */
- loader = PyDict_GetItemString(d, "__loader__");
- if (loader == NULL || loader == Py_None) {
- PyObject *loader = PyObject_GetAttrString(interp->importlib,
- "BuiltinImporter");
- if (loader == NULL) {
+ }
+ Py_DECREF(bimod);
+ }
+
+ /* Main is a little special - imp.is_builtin("__main__") will return
+ * False, but BuiltinImporter is still the most appropriate initial
+ * setting for its __loader__ attribute. A more suitable value will
+ * be set if __main__ gets further initialized later in the startup
+ * process.
+ */
+ loader = PyDict_GetItemString(d, "__loader__");
+ if (loader == NULL || loader == Py_None) {
+ PyObject *loader = PyObject_GetAttrString(interp->importlib,
+ "BuiltinImporter");
+ if (loader == NULL) {
return _PyStatus_ERR("Failed to retrieve BuiltinImporter");
- }
- if (PyDict_SetItemString(d, "__loader__", loader) < 0) {
+ }
+ if (PyDict_SetItemString(d, "__loader__", loader) < 0) {
return _PyStatus_ERR("Failed to initialize __main__.__loader__");
- }
- Py_DECREF(loader);
- }
+ }
+ Py_DECREF(loader);
+ }
return _PyStatus_OK();
-}
-
-/* Import the site module (not into __main__ though) */
-
+}
+
+/* Import the site module (not into __main__ though) */
+
static PyStatus
init_import_site(void)
-{
- PyObject *m;
- m = PyImport_ImportModule("site");
- if (m == NULL) {
+{
+ PyObject *m;
+ m = PyImport_ImportModule("site");
+ if (m == NULL) {
return _PyStatus_ERR("Failed to import the site module");
- }
- Py_DECREF(m);
+ }
+ Py_DECREF(m);
return _PyStatus_OK();
-}
-
-/* Check if a file descriptor is valid or not.
- Return 0 if the file descriptor is invalid, return non-zero otherwise. */
-static int
-is_valid_fd(int fd)
-{
+}
+
+/* Check if a file descriptor is valid or not.
+ Return 0 if the file descriptor is invalid, return non-zero otherwise. */
+static int
+is_valid_fd(int fd)
+{
/* dup() is faster than fstat(): fstat() can require input/output operations,
whereas dup() doesn't. There is a low risk of EMFILE/ENFILE at Python
startup. Problem: dup() doesn't check if the file descriptor is valid on
@@ -1761,112 +1761,112 @@ is_valid_fd(int fd)
if (fd < 0) {
return 0;
}
- int fd2;
+ int fd2;
- _Py_BEGIN_SUPPRESS_IPH
- fd2 = dup(fd);
+ _Py_BEGIN_SUPPRESS_IPH
+ fd2 = dup(fd);
if (fd2 >= 0) {
- close(fd2);
+ close(fd2);
}
- _Py_END_SUPPRESS_IPH
+ _Py_END_SUPPRESS_IPH
return (fd2 >= 0);
#else
struct stat st;
return (fstat(fd, &st) == 0);
-#endif
-}
-
-/* returns Py_None if the fd is not valid */
-static PyObject*
+#endif
+}
+
+/* returns Py_None if the fd is not valid */
+static PyObject*
create_stdio(const PyConfig *config, PyObject* io,
- int fd, int write_mode, const char* name,
+ int fd, int write_mode, const char* name,
const wchar_t* encoding, const wchar_t* errors)
-{
- PyObject *buf = NULL, *stream = NULL, *text = NULL, *raw = NULL, *res;
- const char* mode;
- const char* newline;
- PyObject *line_buffering, *write_through;
- int buffering, isatty;
- _Py_IDENTIFIER(open);
- _Py_IDENTIFIER(isatty);
- _Py_IDENTIFIER(TextIOWrapper);
- _Py_IDENTIFIER(mode);
+{
+ PyObject *buf = NULL, *stream = NULL, *text = NULL, *raw = NULL, *res;
+ const char* mode;
+ const char* newline;
+ PyObject *line_buffering, *write_through;
+ int buffering, isatty;
+ _Py_IDENTIFIER(open);
+ _Py_IDENTIFIER(isatty);
+ _Py_IDENTIFIER(TextIOWrapper);
+ _Py_IDENTIFIER(mode);
const int buffered_stdio = config->buffered_stdio;
-
- if (!is_valid_fd(fd))
- Py_RETURN_NONE;
-
- /* stdin is always opened in buffered mode, first because it shouldn't
- make a difference in common use cases, second because TextIOWrapper
- depends on the presence of a read1() method which only exists on
- buffered streams.
- */
+
+ if (!is_valid_fd(fd))
+ Py_RETURN_NONE;
+
+ /* stdin is always opened in buffered mode, first because it shouldn't
+ make a difference in common use cases, second because TextIOWrapper
+ depends on the presence of a read1() method which only exists on
+ buffered streams.
+ */
if (!buffered_stdio && write_mode)
- buffering = 0;
- else
- buffering = -1;
- if (write_mode)
- mode = "wb";
- else
- mode = "rb";
+ buffering = 0;
+ else
+ buffering = -1;
+ if (write_mode)
+ mode = "wb";
+ else
+ mode = "rb";
buf = _PyObject_CallMethodId(io, &PyId_open, "isiOOOO",
- fd, mode, buffering,
- Py_None, Py_None, /* encoding, errors */
+ fd, mode, buffering,
+ Py_None, Py_None, /* encoding, errors */
Py_None, Py_False); /* newline, closefd */
- if (buf == NULL)
- goto error;
-
- if (buffering) {
- _Py_IDENTIFIER(raw);
- raw = _PyObject_GetAttrId(buf, &PyId_raw);
- if (raw == NULL)
- goto error;
- }
- else {
- raw = buf;
- Py_INCREF(raw);
- }
-
-#ifdef MS_WINDOWS
- /* Windows console IO is always UTF-8 encoded */
- if (PyWindowsConsoleIO_Check(raw))
+ if (buf == NULL)
+ goto error;
+
+ if (buffering) {
+ _Py_IDENTIFIER(raw);
+ raw = _PyObject_GetAttrId(buf, &PyId_raw);
+ if (raw == NULL)
+ goto error;
+ }
+ else {
+ raw = buf;
+ Py_INCREF(raw);
+ }
+
+#ifdef MS_WINDOWS
+ /* Windows console IO is always UTF-8 encoded */
+ if (PyWindowsConsoleIO_Check(raw))
encoding = L"utf-8";
-#endif
-
- text = PyUnicode_FromString(name);
- if (text == NULL || _PyObject_SetAttrId(raw, &PyId_name, text) < 0)
- goto error;
+#endif
+
+ text = PyUnicode_FromString(name);
+ if (text == NULL || _PyObject_SetAttrId(raw, &PyId_name, text) < 0)
+ goto error;
res = _PyObject_CallMethodIdNoArgs(raw, &PyId_isatty);
- if (res == NULL)
- goto error;
- isatty = PyObject_IsTrue(res);
- Py_DECREF(res);
- if (isatty == -1)
- goto error;
+ if (res == NULL)
+ goto error;
+ isatty = PyObject_IsTrue(res);
+ Py_DECREF(res);
+ if (isatty == -1)
+ goto error;
if (!buffered_stdio)
- write_through = Py_True;
- else
- write_through = Py_False;
+ write_through = Py_True;
+ else
+ write_through = Py_False;
if (buffered_stdio && (isatty || fd == fileno(stderr)))
- line_buffering = Py_True;
- else
- line_buffering = Py_False;
-
- Py_CLEAR(raw);
- Py_CLEAR(text);
-
-#ifdef MS_WINDOWS
- /* sys.stdin: enable universal newline mode, translate "\r\n" and "\r"
- newlines to "\n".
- sys.stdout and sys.stderr: translate "\n" to "\r\n". */
- newline = NULL;
-#else
- /* sys.stdin: split lines at "\n".
- sys.stdout and sys.stderr: don't translate newlines (use "\n"). */
- newline = "\n";
-#endif
-
+ line_buffering = Py_True;
+ else
+ line_buffering = Py_False;
+
+ Py_CLEAR(raw);
+ Py_CLEAR(text);
+
+#ifdef MS_WINDOWS
+ /* sys.stdin: enable universal newline mode, translate "\r\n" and "\r"
+ newlines to "\n".
+ sys.stdout and sys.stderr: translate "\n" to "\r\n". */
+ newline = NULL;
+#else
+ /* sys.stdin: split lines at "\n".
+ sys.stdout and sys.stderr: don't translate newlines (use "\n"). */
+ newline = "\n";
+#endif
+
PyObject *encoding_str = PyUnicode_FromWideChar(encoding, -1);
if (encoding_str == NULL) {
Py_CLEAR(buf);
@@ -1882,45 +1882,45 @@ create_stdio(const PyConfig *config, PyObject* io,
stream = _PyObject_CallMethodId(io, &PyId_TextIOWrapper, "OOOsOO",
buf, encoding_str, errors_str,
- newline, line_buffering, write_through);
- Py_CLEAR(buf);
+ newline, line_buffering, write_through);
+ Py_CLEAR(buf);
Py_CLEAR(encoding_str);
Py_CLEAR(errors_str);
- if (stream == NULL)
- goto error;
-
- if (write_mode)
- mode = "w";
- else
- mode = "r";
- text = PyUnicode_FromString(mode);
- if (!text || _PyObject_SetAttrId(stream, &PyId_mode, text) < 0)
- goto error;
- Py_CLEAR(text);
- return stream;
-
-error:
- Py_XDECREF(buf);
- Py_XDECREF(stream);
- Py_XDECREF(text);
- Py_XDECREF(raw);
-
- if (PyErr_ExceptionMatches(PyExc_OSError) && !is_valid_fd(fd)) {
- /* Issue #24891: the file descriptor was closed after the first
- is_valid_fd() check was called. Ignore the OSError and set the
- stream to None. */
- PyErr_Clear();
- Py_RETURN_NONE;
- }
- return NULL;
-}
-
+ if (stream == NULL)
+ goto error;
+
+ if (write_mode)
+ mode = "w";
+ else
+ mode = "r";
+ text = PyUnicode_FromString(mode);
+ if (!text || _PyObject_SetAttrId(stream, &PyId_mode, text) < 0)
+ goto error;
+ Py_CLEAR(text);
+ return stream;
+
+error:
+ Py_XDECREF(buf);
+ Py_XDECREF(stream);
+ Py_XDECREF(text);
+ Py_XDECREF(raw);
+
+ if (PyErr_ExceptionMatches(PyExc_OSError) && !is_valid_fd(fd)) {
+ /* Issue #24891: the file descriptor was closed after the first
+ is_valid_fd() check was called. Ignore the OSError and set the
+ stream to None. */
+ PyErr_Clear();
+ Py_RETURN_NONE;
+ }
+ return NULL;
+}
+
/* Set builtins.open to io.OpenWrapper */
static PyStatus
init_set_builtins_open(void)
-{
- PyObject *iomod = NULL, *wrapper;
- PyObject *bimod = NULL;
+{
+ PyObject *iomod = NULL, *wrapper;
+ PyObject *bimod = NULL;
PyStatus res = _PyStatus_OK();
if (!(iomod = PyImport_ImportModule("io"))) {
@@ -1958,13 +1958,13 @@ static PyStatus
init_sys_streams(PyThreadState *tstate)
{
PyObject *iomod = NULL;
- PyObject *m;
- PyObject *std = NULL;
- int fd;
- PyObject * encoding_attr;
+ PyObject *m;
+ PyObject *std = NULL;
+ int fd;
+ PyObject * encoding_attr;
PyStatus res = _PyStatus_OK();
const PyConfig *config = _PyInterpreterState_GetConfig(tstate->interp);
-
+
/* 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
@@ -1978,198 +1978,198 @@ init_sys_streams(PyThreadState *tstate)
}
#endif
- /* Hack to avoid a nasty recursion issue when Python is invoked
- in verbose mode: pre-import the Latin-1 and UTF-8 codecs */
- if ((m = PyImport_ImportModule("encodings.utf_8")) == NULL) {
- goto error;
- }
- Py_DECREF(m);
-
- if (!(m = PyImport_ImportModule("encodings.latin_1"))) {
- goto error;
- }
- Py_DECREF(m);
-
- if (!(iomod = PyImport_ImportModule("io"))) {
- goto error;
- }
-
- /* Set sys.stdin */
- fd = fileno(stdin);
- /* Under some conditions stdin, stdout and stderr may not be connected
- * and fileno() may point to an invalid file descriptor. For example
- * GUI apps don't have valid standard streams by default.
- */
+ /* Hack to avoid a nasty recursion issue when Python is invoked
+ in verbose mode: pre-import the Latin-1 and UTF-8 codecs */
+ if ((m = PyImport_ImportModule("encodings.utf_8")) == NULL) {
+ goto error;
+ }
+ Py_DECREF(m);
+
+ if (!(m = PyImport_ImportModule("encodings.latin_1"))) {
+ goto error;
+ }
+ Py_DECREF(m);
+
+ if (!(iomod = PyImport_ImportModule("io"))) {
+ goto error;
+ }
+
+ /* Set sys.stdin */
+ fd = fileno(stdin);
+ /* Under some conditions stdin, stdout and stderr may not be connected
+ * and fileno() may point to an invalid file descriptor. For example
+ * GUI apps don't have valid standard streams by default.
+ */
std = create_stdio(config, iomod, fd, 0, "<stdin>",
config->stdio_encoding,
config->stdio_errors);
- if (std == NULL)
- goto error;
- PySys_SetObject("__stdin__", std);
- _PySys_SetObjectId(&PyId_stdin, std);
- Py_DECREF(std);
-
- /* Set sys.stdout */
- fd = fileno(stdout);
+ if (std == NULL)
+ goto error;
+ PySys_SetObject("__stdin__", std);
+ _PySys_SetObjectId(&PyId_stdin, std);
+ Py_DECREF(std);
+
+ /* Set sys.stdout */
+ fd = fileno(stdout);
std = create_stdio(config, iomod, fd, 1, "<stdout>",
config->stdio_encoding,
config->stdio_errors);
- if (std == NULL)
- goto error;
- PySys_SetObject("__stdout__", std);
- _PySys_SetObjectId(&PyId_stdout, std);
- Py_DECREF(std);
-
-#if 1 /* Disable this if you have trouble debugging bootstrap stuff */
- /* Set sys.stderr, replaces the preliminary stderr */
- fd = fileno(stderr);
+ if (std == NULL)
+ goto error;
+ PySys_SetObject("__stdout__", std);
+ _PySys_SetObjectId(&PyId_stdout, std);
+ Py_DECREF(std);
+
+#if 1 /* Disable this if you have trouble debugging bootstrap stuff */
+ /* Set sys.stderr, replaces the preliminary stderr */
+ fd = fileno(stderr);
std = create_stdio(config, iomod, fd, 1, "<stderr>",
config->stdio_encoding,
L"backslashreplace");
- if (std == NULL)
- goto error;
-
- /* Same as hack above, pre-import stderr's codec to avoid recursion
- when import.c tries to write to stderr in verbose mode. */
- encoding_attr = PyObject_GetAttrString(std, "encoding");
- if (encoding_attr != NULL) {
- const char *std_encoding = PyUnicode_AsUTF8(encoding_attr);
- if (std_encoding != NULL) {
- PyObject *codec_info = _PyCodec_Lookup(std_encoding);
- Py_XDECREF(codec_info);
- }
- Py_DECREF(encoding_attr);
- }
+ if (std == NULL)
+ goto error;
+
+ /* Same as hack above, pre-import stderr's codec to avoid recursion
+ when import.c tries to write to stderr in verbose mode. */
+ encoding_attr = PyObject_GetAttrString(std, "encoding");
+ if (encoding_attr != NULL) {
+ const char *std_encoding = PyUnicode_AsUTF8(encoding_attr);
+ if (std_encoding != NULL) {
+ PyObject *codec_info = _PyCodec_Lookup(std_encoding);
+ Py_XDECREF(codec_info);
+ }
+ Py_DECREF(encoding_attr);
+ }
_PyErr_Clear(tstate); /* Not a fatal error if codec isn't available */
-
- if (PySys_SetObject("__stderr__", std) < 0) {
- Py_DECREF(std);
- goto error;
- }
- if (_PySys_SetObjectId(&PyId_stderr, std) < 0) {
- Py_DECREF(std);
- goto error;
- }
- Py_DECREF(std);
-#endif
-
- goto done;
-
-error:
+
+ if (PySys_SetObject("__stderr__", std) < 0) {
+ Py_DECREF(std);
+ goto error;
+ }
+ if (_PySys_SetObjectId(&PyId_stderr, std) < 0) {
+ Py_DECREF(std);
+ goto error;
+ }
+ Py_DECREF(std);
+#endif
+
+ goto done;
+
+error:
res = _PyStatus_ERR("can't initialize sys standard streams");
-
-done:
+
+done:
_Py_ClearStandardStreamEncoding();
- Py_XDECREF(iomod);
- return res;
-}
-
-
-static void
+ Py_XDECREF(iomod);
+ return res;
+}
+
+
+static void
_Py_FatalError_DumpTracebacks(int fd, PyInterpreterState *interp,
PyThreadState *tstate)
-{
- fputc('\n', stderr);
- fflush(stderr);
-
- /* display the current Python stack */
+{
+ fputc('\n', stderr);
+ fflush(stderr);
+
+ /* display the current Python stack */
_Py_DumpTracebackThreads(fd, interp, tstate);
-}
-
-/* Print the current exception (if an exception is set) with its traceback,
- or display the current Python stack.
-
- Don't call PyErr_PrintEx() and the except hook, because Py_FatalError() is
- called on catastrophic cases.
-
- Return 1 if the traceback was displayed, 0 otherwise. */
-
-static int
+}
+
+/* Print the current exception (if an exception is set) with its traceback,
+ or display the current Python stack.
+
+ Don't call PyErr_PrintEx() and the except hook, because Py_FatalError() is
+ called on catastrophic cases.
+
+ Return 1 if the traceback was displayed, 0 otherwise. */
+
+static int
_Py_FatalError_PrintExc(PyThreadState *tstate)
-{
- PyObject *ferr, *res;
- PyObject *exception, *v, *tb;
- int has_tb;
-
+{
+ PyObject *ferr, *res;
+ PyObject *exception, *v, *tb;
+ int has_tb;
+
_PyErr_Fetch(tstate, &exception, &v, &tb);
- if (exception == NULL) {
- /* No current exception */
- return 0;
- }
-
- ferr = _PySys_GetObjectId(&PyId_stderr);
- if (ferr == NULL || ferr == Py_None) {
- /* sys.stderr is not set yet or set to None,
- no need to try to display the exception */
- return 0;
- }
-
+ if (exception == NULL) {
+ /* No current exception */
+ return 0;
+ }
+
+ ferr = _PySys_GetObjectId(&PyId_stderr);
+ if (ferr == NULL || ferr == Py_None) {
+ /* sys.stderr is not set yet or set to None,
+ no need to try to display the exception */
+ return 0;
+ }
+
_PyErr_NormalizeException(tstate, &exception, &v, &tb);
- if (tb == NULL) {
- tb = Py_None;
- Py_INCREF(tb);
- }
- PyException_SetTraceback(v, tb);
- if (exception == NULL) {
- /* PyErr_NormalizeException() failed */
- return 0;
- }
-
- has_tb = (tb != Py_None);
- PyErr_Display(exception, v, tb);
- Py_XDECREF(exception);
- Py_XDECREF(v);
- Py_XDECREF(tb);
-
- /* sys.stderr may be buffered: call sys.stderr.flush() */
+ if (tb == NULL) {
+ tb = Py_None;
+ Py_INCREF(tb);
+ }
+ PyException_SetTraceback(v, tb);
+ if (exception == NULL) {
+ /* PyErr_NormalizeException() failed */
+ return 0;
+ }
+
+ has_tb = (tb != Py_None);
+ PyErr_Display(exception, v, tb);
+ Py_XDECREF(exception);
+ Py_XDECREF(v);
+ Py_XDECREF(tb);
+
+ /* sys.stderr may be buffered: call sys.stderr.flush() */
res = _PyObject_CallMethodIdNoArgs(ferr, &PyId_flush);
if (res == NULL) {
_PyErr_Clear(tstate);
}
else {
- Py_DECREF(res);
- }
-
- return has_tb;
-}
-
-/* Print fatal error message and abort */
-
-#ifdef MS_WINDOWS
-static void
-fatal_output_debug(const char *msg)
-{
- /* buffer of 256 bytes allocated on the stack */
- WCHAR buffer[256 / sizeof(WCHAR)];
- size_t buflen = Py_ARRAY_LENGTH(buffer) - 1;
- size_t msglen;
-
- OutputDebugStringW(L"Fatal Python error: ");
-
- msglen = strlen(msg);
- while (msglen) {
- size_t i;
-
- if (buflen > msglen) {
- buflen = msglen;
- }
-
- /* Convert the message to wchar_t. This uses a simple one-to-one
- conversion, assuming that the this error message actually uses
- ASCII only. If this ceases to be true, we will have to convert. */
- for (i=0; i < buflen; ++i) {
- buffer[i] = msg[i];
- }
- buffer[i] = L'\0';
- OutputDebugStringW(buffer);
-
- msg += buflen;
- msglen -= buflen;
- }
- OutputDebugStringW(L"\n");
-}
-#endif
-
+ Py_DECREF(res);
+ }
+
+ return has_tb;
+}
+
+/* Print fatal error message and abort */
+
+#ifdef MS_WINDOWS
+static void
+fatal_output_debug(const char *msg)
+{
+ /* buffer of 256 bytes allocated on the stack */
+ WCHAR buffer[256 / sizeof(WCHAR)];
+ size_t buflen = Py_ARRAY_LENGTH(buffer) - 1;
+ size_t msglen;
+
+ OutputDebugStringW(L"Fatal Python error: ");
+
+ msglen = strlen(msg);
+ while (msglen) {
+ size_t i;
+
+ if (buflen > msglen) {
+ buflen = msglen;
+ }
+
+ /* Convert the message to wchar_t. This uses a simple one-to-one
+ conversion, assuming that the this error message actually uses
+ ASCII only. If this ceases to be true, we will have to convert. */
+ for (i=0; i < buflen; ++i) {
+ buffer[i] = msg[i];
+ }
+ buffer[i] = L'\0';
+ OutputDebugStringW(buffer);
+
+ msg += buflen;
+ msglen -= buflen;
+ }
+ OutputDebugStringW(L"\n");
+}
+#endif
+
static void
fatal_error_dump_runtime(FILE *stream, _PyRuntimeState *runtime)
@@ -2214,20 +2214,20 @@ fatal_error_exit(int status)
}
-static void _Py_NO_RETURN
+static void _Py_NO_RETURN
fatal_error(FILE *stream, int header, const char *prefix, const char *msg,
int status)
-{
+{
const int fd = fileno(stream);
- static int reentrant = 0;
-
- if (reentrant) {
- /* Py_FatalError() caused a second fatal error.
- Example: flush_std_files() raises a recursion error. */
+ static int reentrant = 0;
+
+ if (reentrant) {
+ /* Py_FatalError() caused a second fatal error.
+ Example: flush_std_files() raises a recursion error. */
fatal_error_exit(status);
- }
- reentrant = 1;
-
+ }
+ reentrant = 1;
+
if (header) {
fprintf(stream, "Fatal Python error: ");
if (prefix) {
@@ -2242,8 +2242,8 @@ fatal_error(FILE *stream, int header, const char *prefix, const char *msg,
}
fputs("\n", stream);
fflush(stream);
- }
-
+ }
+
_PyRuntimeState *runtime = &_PyRuntime;
fatal_error_dump_runtime(stream, runtime);
@@ -2253,7 +2253,7 @@ fatal_error(FILE *stream, int header, const char *prefix, const char *msg,
interp = tstate->interp;
}
- /* Check if the current thread has a Python thread state
+ /* Check if the current thread has a Python thread state
and holds the GIL.
tss_tstate is NULL if Py_FatalError() is called from a C thread which
@@ -2261,49 +2261,49 @@ fatal_error(FILE *stream, int header, const char *prefix, const char *msg,
tss_tstate != tstate if the current Python thread does not hold the GIL.
*/
- PyThreadState *tss_tstate = PyGILState_GetThisThreadState();
+ PyThreadState *tss_tstate = PyGILState_GetThisThreadState();
int has_tstate_and_gil = (tss_tstate != NULL && tss_tstate == tstate);
- if (has_tstate_and_gil) {
- /* If an exception is set, print the exception with its traceback */
+ if (has_tstate_and_gil) {
+ /* If an exception is set, print the exception with its traceback */
if (!_Py_FatalError_PrintExc(tss_tstate)) {
- /* No exception is set, or an exception is set without traceback */
+ /* No exception is set, or an exception is set without traceback */
_Py_FatalError_DumpTracebacks(fd, interp, tss_tstate);
- }
- }
- else {
+ }
+ }
+ else {
_Py_FatalError_DumpTracebacks(fd, interp, tss_tstate);
- }
-
- /* The main purpose of faulthandler is to display the traceback.
- This function already did its best to display a traceback.
- Disable faulthandler to prevent writing a second traceback
- on abort(). */
- _PyFaulthandler_Fini();
-
- /* Check if the current Python thread hold the GIL */
- if (has_tstate_and_gil) {
- /* Flush sys.stdout and sys.stderr */
- flush_std_files();
- }
-
-#ifdef MS_WINDOWS
- fatal_output_debug(msg);
-#endif /* MS_WINDOWS */
-
+ }
+
+ /* The main purpose of faulthandler is to display the traceback.
+ This function already did its best to display a traceback.
+ Disable faulthandler to prevent writing a second traceback
+ on abort(). */
+ _PyFaulthandler_Fini();
+
+ /* Check if the current Python thread hold the GIL */
+ if (has_tstate_and_gil) {
+ /* Flush sys.stdout and sys.stderr */
+ flush_std_files();
+ }
+
+#ifdef MS_WINDOWS
+ fatal_output_debug(msg);
+#endif /* MS_WINDOWS */
+
fatal_error_exit(status);
-}
-
+}
+
#undef Py_FatalError
-void _Py_NO_RETURN
-Py_FatalError(const char *msg)
-{
+void _Py_NO_RETURN
+Py_FatalError(const char *msg)
+{
fatal_error(stderr, 1, NULL, msg, -1);
-}
-
+}
+
-void _Py_NO_RETURN
+void _Py_NO_RETURN
_Py_FatalErrorFunc(const char *func, const char *msg)
{
fatal_error(stderr, 1, func, msg, -1);
@@ -2346,7 +2346,7 @@ _Py_FatalErrorFormat(const char *func, const char *format, ...)
void _Py_NO_RETURN
Py_ExitStatusException(PyStatus status)
-{
+{
if (_PyStatus_IS_EXIT(status)) {
exit(status.exitcode);
}
@@ -2356,204 +2356,204 @@ Py_ExitStatusException(PyStatus status)
else {
Py_FatalError("Py_ExitStatusException() must not be called on success");
}
-}
-
-/* Clean up and exit */
-
-/* For the atexit module. */
-void _Py_PyAtExit(void (*func)(PyObject *), PyObject *module)
-{
+}
+
+/* Clean up and exit */
+
+/* For the atexit module. */
+void _Py_PyAtExit(void (*func)(PyObject *), PyObject *module)
+{
PyInterpreterState *is = _PyInterpreterState_GET();
-
- /* Guard against API misuse (see bpo-17852) */
- assert(is->pyexitfunc == NULL || is->pyexitfunc == func);
-
- is->pyexitfunc = func;
- is->pyexitmodule = module;
-}
-
-static void
+
+ /* Guard against API misuse (see bpo-17852) */
+ assert(is->pyexitfunc == NULL || is->pyexitfunc == func);
+
+ is->pyexitfunc = func;
+ is->pyexitmodule = module;
+}
+
+static void
call_py_exitfuncs(PyThreadState *tstate)
-{
+{
PyInterpreterState *interp = tstate->interp;
if (interp->pyexitfunc == NULL)
- return;
-
+ return;
+
(*interp->pyexitfunc)(interp->pyexitmodule);
_PyErr_Clear(tstate);
-}
-
-/* Wait until threading._shutdown completes, provided
- the threading module was imported in the first place.
- The shutdown routine will wait until all non-daemon
- "threading" threads have completed. */
-static void
+}
+
+/* Wait until threading._shutdown completes, provided
+ the threading module was imported in the first place.
+ The shutdown routine will wait until all non-daemon
+ "threading" threads have completed. */
+static void
wait_for_thread_shutdown(PyThreadState *tstate)
-{
- _Py_IDENTIFIER(_shutdown);
- PyObject *result;
- PyObject *threading = _PyImport_GetModuleId(&PyId_threading);
- if (threading == NULL) {
+{
+ _Py_IDENTIFIER(_shutdown);
+ PyObject *result;
+ PyObject *threading = _PyImport_GetModuleId(&PyId_threading);
+ if (threading == NULL) {
if (_PyErr_Occurred(tstate)) {
PyErr_WriteUnraisable(NULL);
}
/* else: threading not imported */
- return;
- }
+ return;
+ }
result = _PyObject_CallMethodIdNoArgs(threading, &PyId__shutdown);
- if (result == NULL) {
- PyErr_WriteUnraisable(threading);
- }
- else {
- Py_DECREF(result);
- }
- Py_DECREF(threading);
-}
-
-#define NEXITFUNCS 32
-int Py_AtExit(void (*func)(void))
-{
- if (_PyRuntime.nexitfuncs >= NEXITFUNCS)
- return -1;
- _PyRuntime.exitfuncs[_PyRuntime.nexitfuncs++] = func;
- return 0;
-}
-
-static void
+ if (result == NULL) {
+ PyErr_WriteUnraisable(threading);
+ }
+ else {
+ Py_DECREF(result);
+ }
+ Py_DECREF(threading);
+}
+
+#define NEXITFUNCS 32
+int Py_AtExit(void (*func)(void))
+{
+ if (_PyRuntime.nexitfuncs >= NEXITFUNCS)
+ return -1;
+ _PyRuntime.exitfuncs[_PyRuntime.nexitfuncs++] = func;
+ return 0;
+}
+
+static void
call_ll_exitfuncs(_PyRuntimeState *runtime)
-{
+{
while (runtime->nexitfuncs > 0) {
/* pop last function from the list */
runtime->nexitfuncs--;
void (*exitfunc)(void) = runtime->exitfuncs[runtime->nexitfuncs];
runtime->exitfuncs[runtime->nexitfuncs] = NULL;
-
+
exitfunc();
}
- fflush(stdout);
- fflush(stderr);
-}
-
+ fflush(stdout);
+ fflush(stderr);
+}
+
void _Py_NO_RETURN
-Py_Exit(int sts)
-{
- if (Py_FinalizeEx() < 0) {
- sts = 120;
- }
-
- exit(sts);
-}
-
-
-/* Restore signals that the interpreter has called SIG_IGN on to SIG_DFL.
- *
- * All of the code in this function must only use async-signal-safe functions,
- * listed at `man 7 signal` or
- * http://www.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_04.html.
+Py_Exit(int sts)
+{
+ if (Py_FinalizeEx() < 0) {
+ sts = 120;
+ }
+
+ exit(sts);
+}
+
+
+/* Restore signals that the interpreter has called SIG_IGN on to SIG_DFL.
+ *
+ * All of the code in this function must only use async-signal-safe functions,
+ * listed at `man 7 signal` or
+ * http://www.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_04.html.
*
* If this function is updated, update also _posix_spawn() of subprocess.py.
- */
-void
-_Py_RestoreSignals(void)
-{
-#ifdef SIGPIPE
- PyOS_setsig(SIGPIPE, SIG_DFL);
-#endif
-#ifdef SIGXFZ
- PyOS_setsig(SIGXFZ, SIG_DFL);
-#endif
-#ifdef SIGXFSZ
- PyOS_setsig(SIGXFSZ, SIG_DFL);
-#endif
-}
-
-
-/*
- * The file descriptor fd is considered ``interactive'' if either
- * a) isatty(fd) is TRUE, or
- * b) the -i flag was given, and the filename associated with
- * the descriptor is NULL or "<stdin>" or "???".
- */
-int
-Py_FdIsInteractive(FILE *fp, const char *filename)
-{
- if (isatty((int)fileno(fp)))
- return 1;
- if (!Py_InteractiveFlag)
- return 0;
- return (filename == NULL) ||
- (strcmp(filename, "<stdin>") == 0) ||
- (strcmp(filename, "???") == 0);
-}
-
-
-/* Wrappers around sigaction() or signal(). */
-
-PyOS_sighandler_t
-PyOS_getsig(int sig)
-{
-#ifdef HAVE_SIGACTION
- struct sigaction context;
- if (sigaction(sig, NULL, &context) == -1)
- return SIG_ERR;
- return context.sa_handler;
-#else
- PyOS_sighandler_t handler;
-/* Special signal handling for the secure CRT in Visual Studio 2005 */
-#if defined(_MSC_VER) && _MSC_VER >= 1400
- switch (sig) {
- /* Only these signals are valid */
- case SIGINT:
- case SIGILL:
- case SIGFPE:
- case SIGSEGV:
- case SIGTERM:
- case SIGBREAK:
- case SIGABRT:
- break;
- /* Don't call signal() with other values or it will assert */
- default:
- return SIG_ERR;
- }
-#endif /* _MSC_VER && _MSC_VER >= 1400 */
- handler = signal(sig, SIG_IGN);
- if (handler != SIG_ERR)
- signal(sig, handler);
- return handler;
-#endif
-}
-
-/*
- * All of the code in this function must only use async-signal-safe functions,
- * listed at `man 7 signal` or
- * http://www.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_04.html.
- */
-PyOS_sighandler_t
-PyOS_setsig(int sig, PyOS_sighandler_t handler)
-{
-#ifdef HAVE_SIGACTION
- /* Some code in Modules/signalmodule.c depends on sigaction() being
- * used here if HAVE_SIGACTION is defined. Fix that if this code
- * changes to invalidate that assumption.
- */
- struct sigaction context, ocontext;
- context.sa_handler = handler;
- sigemptyset(&context.sa_mask);
- context.sa_flags = 0;
- if (sigaction(sig, &context, &ocontext) == -1)
- return SIG_ERR;
- return ocontext.sa_handler;
-#else
- PyOS_sighandler_t oldhandler;
- oldhandler = signal(sig, handler);
-#ifdef HAVE_SIGINTERRUPT
- siginterrupt(sig, 1);
-#endif
- return oldhandler;
-#endif
-}
-
-#ifdef __cplusplus
-}
-#endif
+ */
+void
+_Py_RestoreSignals(void)
+{
+#ifdef SIGPIPE
+ PyOS_setsig(SIGPIPE, SIG_DFL);
+#endif
+#ifdef SIGXFZ
+ PyOS_setsig(SIGXFZ, SIG_DFL);
+#endif
+#ifdef SIGXFSZ
+ PyOS_setsig(SIGXFSZ, SIG_DFL);
+#endif
+}
+
+
+/*
+ * The file descriptor fd is considered ``interactive'' if either
+ * a) isatty(fd) is TRUE, or
+ * b) the -i flag was given, and the filename associated with
+ * the descriptor is NULL or "<stdin>" or "???".
+ */
+int
+Py_FdIsInteractive(FILE *fp, const char *filename)
+{
+ if (isatty((int)fileno(fp)))
+ return 1;
+ if (!Py_InteractiveFlag)
+ return 0;
+ return (filename == NULL) ||
+ (strcmp(filename, "<stdin>") == 0) ||
+ (strcmp(filename, "???") == 0);
+}
+
+
+/* Wrappers around sigaction() or signal(). */
+
+PyOS_sighandler_t
+PyOS_getsig(int sig)
+{
+#ifdef HAVE_SIGACTION
+ struct sigaction context;
+ if (sigaction(sig, NULL, &context) == -1)
+ return SIG_ERR;
+ return context.sa_handler;
+#else
+ PyOS_sighandler_t handler;
+/* Special signal handling for the secure CRT in Visual Studio 2005 */
+#if defined(_MSC_VER) && _MSC_VER >= 1400
+ switch (sig) {
+ /* Only these signals are valid */
+ case SIGINT:
+ case SIGILL:
+ case SIGFPE:
+ case SIGSEGV:
+ case SIGTERM:
+ case SIGBREAK:
+ case SIGABRT:
+ break;
+ /* Don't call signal() with other values or it will assert */
+ default:
+ return SIG_ERR;
+ }
+#endif /* _MSC_VER && _MSC_VER >= 1400 */
+ handler = signal(sig, SIG_IGN);
+ if (handler != SIG_ERR)
+ signal(sig, handler);
+ return handler;
+#endif
+}
+
+/*
+ * All of the code in this function must only use async-signal-safe functions,
+ * listed at `man 7 signal` or
+ * http://www.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_04.html.
+ */
+PyOS_sighandler_t
+PyOS_setsig(int sig, PyOS_sighandler_t handler)
+{
+#ifdef HAVE_SIGACTION
+ /* Some code in Modules/signalmodule.c depends on sigaction() being
+ * used here if HAVE_SIGACTION is defined. Fix that if this code
+ * changes to invalidate that assumption.
+ */
+ struct sigaction context, ocontext;
+ context.sa_handler = handler;
+ sigemptyset(&context.sa_mask);
+ context.sa_flags = 0;
+ if (sigaction(sig, &context, &ocontext) == -1)
+ return SIG_ERR;
+ return ocontext.sa_handler;
+#else
+ PyOS_sighandler_t oldhandler;
+ oldhandler = signal(sig, handler);
+#ifdef HAVE_SIGINTERRUPT
+ siginterrupt(sig, 1);
+#endif
+ return oldhandler;
+#endif
+}
+
+#ifdef __cplusplus
+}
+#endif