summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Include/Python.h1
-rw-r--r--Include/object.h7
-rw-r--r--Include/pydebug.h2
-rw-r--r--Include/pyerrors.h1
-rw-r--r--Include/pylifecycle.h124
-rw-r--r--Include/pythonrun.h110
-rw-r--r--Lib/_pyio.py2
-rw-r--r--Makefile.pre.in2
-rw-r--r--Misc/NEWS3
-rw-r--r--Modules/atexitmodule.c2
-rw-r--r--Modules/signalmodule.c2
-rw-r--r--Objects/object.c16
-rw-r--r--Python/compile.c2
-rw-r--r--Python/pylifecycle.c1540
-rw-r--r--Python/pythonrun.c1472
-rw-r--r--Python/sysmodule.c2
16 files changed, 1701 insertions, 1587 deletions
diff --git a/Include/Python.h b/Include/Python.h
index 2dd8290..46d2ece 100644
--- a/Include/Python.h
+++ b/Include/Python.h
@@ -112,6 +112,7 @@
#include "pyarena.h"
#include "modsupport.h"
#include "pythonrun.h"
+#include "pylifecycle.h"
#include "ceval.h"
#include "sysmodule.h"
#include "intrcheck.h"
diff --git a/Include/object.h b/Include/object.h
index e348d61..e29608a 100644
--- a/Include/object.h
+++ b/Include/object.h
@@ -65,6 +65,7 @@ whose size is determined when the object is allocated.
#error Py_LIMITED_API is incompatible with Py_DEBUG, Py_TRACE_REFS, and Py_REF_DEBUG
#endif
+
#ifdef Py_TRACE_REFS
/* Define pointers to support a doubly-linked list of all live heap objects. */
#define _PyObject_HEAD_EXTRA \
@@ -710,11 +711,17 @@ PyAPI_FUNC(Py_ssize_t) _Py_GetRefTotal(void);
_Py_NegativeRefcount(__FILE__, __LINE__, \
(PyObject *)(OP)); \
}
+/* Py_REF_DEBUG also controls the display of refcounts and memory block
+ * allocations at the interactive prompt and at interpreter shutdown
+ */
+PyAPI_FUNC(void) _PyDebug_PrintTotalRefs(void);
+#define _PY_DEBUG_PRINT_TOTAL_REFS() _PyDebug_PrintTotalRefs()
#else
#define _Py_INC_REFTOTAL
#define _Py_DEC_REFTOTAL
#define _Py_REF_DEBUG_COMMA
#define _Py_CHECK_REFCNT(OP) /* a semicolon */;
+#define _PY_DEBUG_PRINT_TOTAL_REFS()
#endif /* Py_REF_DEBUG */
#ifdef COUNT_ALLOCS
diff --git a/Include/pydebug.h b/Include/pydebug.h
index 8fe9818..19bec2b 100644
--- a/Include/pydebug.h
+++ b/Include/pydebug.h
@@ -5,6 +5,8 @@
extern "C" {
#endif
+/* These global variable are defined in pylifecycle.c */
+/* XXX (ncoghlan): move these declarations to pylifecycle.h? */
PyAPI_DATA(int) Py_DebugFlag;
PyAPI_DATA(int) Py_VerboseFlag;
PyAPI_DATA(int) Py_QuietFlag;
diff --git a/Include/pyerrors.h b/Include/pyerrors.h
index 65b09f0..8a7e4f4 100644
--- a/Include/pyerrors.h
+++ b/Include/pyerrors.h
@@ -99,6 +99,7 @@ PyAPI_FUNC(void) PyErr_SetExcInfo(PyObject *, PyObject *, PyObject *);
#define _Py_NO_RETURN
#endif
+/* Defined in Python/pylifecycle.c */
PyAPI_FUNC(void) Py_FatalError(const char *message) _Py_NO_RETURN;
#if defined(Py_DEBUG) || defined(Py_LIMITED_API)
diff --git a/Include/pylifecycle.h b/Include/pylifecycle.h
new file mode 100644
index 0000000..ccdebe2
--- /dev/null
+++ b/Include/pylifecycle.h
@@ -0,0 +1,124 @@
+
+/* Interfaces to configure, query, create & destroy the Python runtime */
+
+#ifndef Py_PYLIFECYCLE_H
+#define Py_PYLIFECYCLE_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+PyAPI_FUNC(void) Py_SetProgramName(wchar_t *);
+PyAPI_FUNC(wchar_t *) Py_GetProgramName(void);
+
+PyAPI_FUNC(void) Py_SetPythonHome(wchar_t *);
+PyAPI_FUNC(wchar_t *) Py_GetPythonHome(void);
+
+#ifndef Py_LIMITED_API
+/* Only used by applications that embed the interpreter and need to
+ * override the standard encoding determination mechanism
+ */
+PyAPI_FUNC(int) Py_SetStandardStreamEncoding(const char *encoding,
+ const char *errors);
+#endif
+
+PyAPI_FUNC(void) Py_Initialize(void);
+PyAPI_FUNC(void) Py_InitializeEx(int);
+#ifndef Py_LIMITED_API
+PyAPI_FUNC(void) _Py_InitializeEx_Private(int, int);
+#endif
+PyAPI_FUNC(void) Py_Finalize(void);
+PyAPI_FUNC(int) Py_IsInitialized(void);
+PyAPI_FUNC(PyThreadState *) Py_NewInterpreter(void);
+PyAPI_FUNC(void) Py_EndInterpreter(PyThreadState *);
+
+
+/* Py_PyAtExit is for the atexit module, Py_AtExit is for low-level
+ * exit functions.
+ */
+#ifndef Py_LIMITED_API
+PyAPI_FUNC(void) _Py_PyAtExit(void (*func)(void));
+#endif
+PyAPI_FUNC(int) Py_AtExit(void (*func)(void));
+
+PyAPI_FUNC(void) Py_Exit(int);
+
+/* Restore signals that the interpreter has called SIG_IGN on to SIG_DFL. */
+#ifndef Py_LIMITED_API
+PyAPI_FUNC(void) _Py_RestoreSignals(void);
+
+PyAPI_FUNC(int) Py_FdIsInteractive(FILE *, const char *);
+#endif
+
+/* Bootstrap __main__ (defined in Modules/main.c) */
+PyAPI_FUNC(int) Py_Main(int argc, wchar_t **argv);
+
+/* In getpath.c */
+PyAPI_FUNC(wchar_t *) Py_GetProgramFullPath(void);
+PyAPI_FUNC(wchar_t *) Py_GetPrefix(void);
+PyAPI_FUNC(wchar_t *) Py_GetExecPrefix(void);
+PyAPI_FUNC(wchar_t *) Py_GetPath(void);
+PyAPI_FUNC(void) Py_SetPath(const wchar_t *);
+#ifdef MS_WINDOWS
+int _Py_CheckPython3();
+#endif
+
+/* In their own files */
+PyAPI_FUNC(const char *) Py_GetVersion(void);
+PyAPI_FUNC(const char *) Py_GetPlatform(void);
+PyAPI_FUNC(const char *) Py_GetCopyright(void);
+PyAPI_FUNC(const char *) Py_GetCompiler(void);
+PyAPI_FUNC(const char *) Py_GetBuildInfo(void);
+#ifndef Py_LIMITED_API
+PyAPI_FUNC(const char *) _Py_hgidentifier(void);
+PyAPI_FUNC(const char *) _Py_hgversion(void);
+#endif
+
+/* Internal -- various one-time initializations */
+#ifndef Py_LIMITED_API
+PyAPI_FUNC(PyObject *) _PyBuiltin_Init(void);
+PyAPI_FUNC(PyObject *) _PySys_Init(void);
+PyAPI_FUNC(void) _PyImport_Init(void);
+PyAPI_FUNC(void) _PyExc_Init(PyObject * bltinmod);
+PyAPI_FUNC(void) _PyImportHooks_Init(void);
+PyAPI_FUNC(int) _PyFrame_Init(void);
+PyAPI_FUNC(int) _PyFloat_Init(void);
+PyAPI_FUNC(int) PyByteArray_Init(void);
+PyAPI_FUNC(void) _PyRandom_Init(void);
+#endif
+
+/* Various internal finalizers */
+#ifndef Py_LIMITED_API
+PyAPI_FUNC(void) _PyExc_Fini(void);
+PyAPI_FUNC(void) _PyImport_Fini(void);
+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) _PyGC_DumpShutdownStats(void);
+PyAPI_FUNC(void) _PyGC_Fini(void);
+PyAPI_FUNC(void) PySlice_Fini(void);
+PyAPI_FUNC(void) _PyType_Fini(void);
+PyAPI_FUNC(void) _PyRandom_Fini(void);
+
+PyAPI_DATA(PyThreadState *) _Py_Finalizing;
+#endif
+
+/* Signals */
+typedef void (*PyOS_sighandler_t)(int);
+PyAPI_FUNC(PyOS_sighandler_t) PyOS_getsig(int);
+PyAPI_FUNC(PyOS_sighandler_t) PyOS_setsig(int, PyOS_sighandler_t);
+
+/* Random */
+PyAPI_FUNC(int) _PyOS_URandom (void *buffer, Py_ssize_t size);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !Py_PYLIFECYCLE_H */
diff --git a/Include/pythonrun.h b/Include/pythonrun.h
index 2fc5578..1d9b71b 100644
--- a/Include/pythonrun.h
+++ b/Include/pythonrun.h
@@ -22,30 +22,6 @@ typedef struct {
} PyCompilerFlags;
#endif
-PyAPI_FUNC(void) Py_SetProgramName(wchar_t *);
-PyAPI_FUNC(wchar_t *) Py_GetProgramName(void);
-
-PyAPI_FUNC(void) Py_SetPythonHome(wchar_t *);
-PyAPI_FUNC(wchar_t *) Py_GetPythonHome(void);
-
-#ifndef Py_LIMITED_API
-/* Only used by applications that embed the interpreter and need to
- * override the standard encoding determination mechanism
- */
-PyAPI_FUNC(int) Py_SetStandardStreamEncoding(const char *encoding,
- const char *errors);
-#endif
-
-PyAPI_FUNC(void) Py_Initialize(void);
-PyAPI_FUNC(void) Py_InitializeEx(int);
-#ifndef Py_LIMITED_API
-PyAPI_FUNC(void) _Py_InitializeEx_Private(int, int);
-#endif
-PyAPI_FUNC(void) Py_Finalize(void);
-PyAPI_FUNC(int) Py_IsInitialized(void);
-PyAPI_FUNC(PyThreadState *) Py_NewInterpreter(void);
-PyAPI_FUNC(void) Py_EndInterpreter(PyThreadState *);
-
#ifndef Py_LIMITED_API
PyAPI_FUNC(int) PyRun_SimpleStringFlags(const char *, PyCompilerFlags *);
PyAPI_FUNC(int) PyRun_AnyFileFlags(FILE *, const char *, PyCompilerFlags *);
@@ -166,26 +142,6 @@ PyAPI_FUNC(void) PyErr_Print(void);
PyAPI_FUNC(void) PyErr_PrintEx(int);
PyAPI_FUNC(void) PyErr_Display(PyObject *, PyObject *, PyObject *);
-/* Py_PyAtExit is for the atexit module, Py_AtExit is for low-level
- * exit functions.
- */
-#ifndef Py_LIMITED_API
-PyAPI_FUNC(void) _Py_PyAtExit(void (*func)(void));
-#endif
-PyAPI_FUNC(int) Py_AtExit(void (*func)(void));
-
-PyAPI_FUNC(void) Py_Exit(int);
-
-/* Restore signals that the interpreter has called SIG_IGN on to SIG_DFL. */
-#ifndef Py_LIMITED_API
-PyAPI_FUNC(void) _Py_RestoreSignals(void);
-
-PyAPI_FUNC(int) Py_FdIsInteractive(FILE *, const char *);
-#endif
-
-/* Bootstrap */
-PyAPI_FUNC(int) Py_Main(int argc, wchar_t **argv);
-
#ifndef Py_LIMITED_API
/* Use macros for a bunch of old variants */
#define PyRun_String(str, s, g, l) PyRun_StringFlags(str, s, g, l, NULL)
@@ -207,64 +163,6 @@ PyAPI_FUNC(int) Py_Main(int argc, wchar_t **argv);
PyRun_FileExFlags(fp, p, s, g, l, 0, flags)
#endif
-/* In getpath.c */
-PyAPI_FUNC(wchar_t *) Py_GetProgramFullPath(void);
-PyAPI_FUNC(wchar_t *) Py_GetPrefix(void);
-PyAPI_FUNC(wchar_t *) Py_GetExecPrefix(void);
-PyAPI_FUNC(wchar_t *) Py_GetPath(void);
-PyAPI_FUNC(void) Py_SetPath(const wchar_t *);
-#ifdef MS_WINDOWS
-int _Py_CheckPython3();
-#endif
-
-/* In their own files */
-PyAPI_FUNC(const char *) Py_GetVersion(void);
-PyAPI_FUNC(const char *) Py_GetPlatform(void);
-PyAPI_FUNC(const char *) Py_GetCopyright(void);
-PyAPI_FUNC(const char *) Py_GetCompiler(void);
-PyAPI_FUNC(const char *) Py_GetBuildInfo(void);
-#ifndef Py_LIMITED_API
-PyAPI_FUNC(const char *) _Py_hgidentifier(void);
-PyAPI_FUNC(const char *) _Py_hgversion(void);
-#endif
-
-/* Internal -- various one-time initializations */
-#ifndef Py_LIMITED_API
-PyAPI_FUNC(PyObject *) _PyBuiltin_Init(void);
-PyAPI_FUNC(PyObject *) _PySys_Init(void);
-PyAPI_FUNC(void) _PyImport_Init(void);
-PyAPI_FUNC(void) _PyExc_Init(PyObject * bltinmod);
-PyAPI_FUNC(void) _PyImportHooks_Init(void);
-PyAPI_FUNC(int) _PyFrame_Init(void);
-PyAPI_FUNC(int) _PyFloat_Init(void);
-PyAPI_FUNC(int) PyByteArray_Init(void);
-PyAPI_FUNC(void) _PyRandom_Init(void);
-#endif
-
-/* Various internal finalizers */
-#ifndef Py_LIMITED_API
-PyAPI_FUNC(void) _PyExc_Fini(void);
-PyAPI_FUNC(void) _PyImport_Fini(void);
-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) _PyGC_DumpShutdownStats(void);
-PyAPI_FUNC(void) _PyGC_Fini(void);
-PyAPI_FUNC(void) PySlice_Fini(void);
-PyAPI_FUNC(void) _PyType_Fini(void);
-PyAPI_FUNC(void) _PyRandom_Fini(void);
-
-PyAPI_DATA(PyThreadState *) _Py_Finalizing;
-#endif
-
/* Stuff with no proper home (yet) */
#ifndef Py_LIMITED_API
PyAPI_FUNC(char *) PyOS_Readline(FILE *, FILE *, const char *);
@@ -290,14 +188,6 @@ PyAPI_DATA(PyThreadState*) _PyOS_ReadlineTState;
PyAPI_FUNC(int) PyOS_CheckStack(void);
#endif
-/* Signals */
-typedef void (*PyOS_sighandler_t)(int);
-PyAPI_FUNC(PyOS_sighandler_t) PyOS_getsig(int);
-PyAPI_FUNC(PyOS_sighandler_t) PyOS_setsig(int, PyOS_sighandler_t);
-
-/* Random */
-PyAPI_FUNC(int) _PyOS_URandom (void *buffer, Py_ssize_t size);
-
#ifdef __cplusplus
}
#endif
diff --git a/Lib/_pyio.py b/Lib/_pyio.py
index d23b032..d507cfe 100644
--- a/Lib/_pyio.py
+++ b/Lib/_pyio.py
@@ -257,7 +257,7 @@ class OpenWrapper:
Trick so that open won't become a bound method when stored
as a class variable (as dbm.dumb does).
- See initstdio() in Python/pythonrun.c.
+ See initstdio() in Python/pylifecycle.c.
"""
__doc__ = DocDescriptor()
diff --git a/Makefile.pre.in b/Makefile.pre.in
index 894b08e..89d7e72 100644
--- a/Makefile.pre.in
+++ b/Makefile.pre.in
@@ -389,6 +389,7 @@ PYTHON_OBJS= \
Python/pyctype.o \
Python/pyfpe.o \
Python/pyhash.o \
+ Python/pylifecycle.o \
Python/pymath.o \
Python/pystate.o \
Python/pythonrun.o \
@@ -909,6 +910,7 @@ PYTHON_HEADERS= \
$(srcdir)/Include/pyerrors.h \
$(srcdir)/Include/pyfpe.h \
$(srcdir)/Include/pyhash.h \
+ $(srcdir)/Include/pylifecycle.h \
$(srcdir)/Include/pymath.h \
$(srcdir)/Include/pygetopt.h \
$(srcdir)/Include/pymacro.h \
diff --git a/Misc/NEWS b/Misc/NEWS
index 30df605..7d97ae6 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,9 @@ Release date: TBA
Core and Builtins
-----------------
+- Issue #22869: Move the interpreter startup & shutdown code to a new
+ dedicated pylifecycle.c module
+
- Issue #22847: Improve method cache efficiency.
- Issue #22335: Fix crash when trying to enlarge a bytearray to 0x7fffffff
diff --git a/Modules/atexitmodule.c b/Modules/atexitmodule.c
index 9887014..79e9962 100644
--- a/Modules/atexitmodule.c
+++ b/Modules/atexitmodule.c
@@ -60,7 +60,7 @@ atexit_cleanup(atexitmodule_state *modstate)
modstate->ncallbacks = 0;
}
-/* Installed into pythonrun.c's atexit mechanism */
+/* Installed into pylifecycle.c's atexit mechanism */
static void
atexit_callfuncs(void)
diff --git a/Modules/signalmodule.c b/Modules/signalmodule.c
index 38c5d21..eabe2f0 100644
--- a/Modules/signalmodule.c
+++ b/Modules/signalmodule.c
@@ -304,7 +304,7 @@ signal_handler(int sig_num)
if (sig_num != SIGCHLD)
#endif
/* If the handler was not set up with sigaction, reinstall it. See
- * Python/pythonrun.c for the implementation of PyOS_setsig which
+ * Python/pylifecycle.c for the implementation of PyOS_setsig which
* makes this true. See also issue8354. */
PyOS_setsig(sig_num, signal_handler);
#endif
diff --git a/Objects/object.c b/Objects/object.c
index b9ae23a..42cbbcd 100644
--- a/Objects/object.c
+++ b/Objects/object.c
@@ -33,6 +33,22 @@ _Py_GetRefTotal(void)
total -= o->ob_refcnt;
return total;
}
+
+void
+_PyDebug_PrintTotalRefs(void) {
+ PyObject *xoptions, *value;
+ _Py_IDENTIFIER(showrefcount);
+
+ xoptions = PySys_GetXOptions();
+ if (xoptions == NULL)
+ return;
+ value = _PyDict_GetItemId(xoptions, &PyId_showrefcount);
+ if (value == Py_True)
+ fprintf(stderr,
+ "[%" PY_FORMAT_SIZE_T "d refs, "
+ "%" PY_FORMAT_SIZE_T "d blocks]\n",
+ _Py_GetRefTotal(), _Py_GetAllocatedBlocks());
+}
#endif /* Py_REF_DEBUG */
/* Object allocation routines used by NEWOBJ and NEWVAROBJ macros.
diff --git a/Python/compile.c b/Python/compile.c
index ac9decc..8abe50f 100644
--- a/Python/compile.c
+++ b/Python/compile.c
@@ -30,8 +30,6 @@
#include "symtable.h"
#include "opcode.h"
-int Py_OptimizeFlag = 0;
-
#define DEFAULT_BLOCK_SIZE 16
#define DEFAULT_BLOCKS 8
#define DEFAULT_CODE_SIZE 128
diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c
new file mode 100644
index 0000000..077c013
--- /dev/null
+++ b/Python/pylifecycle.c
@@ -0,0 +1,1540 @@
+
+/* Python interpreter top-level routines, including init/exit */
+
+#include "Python.h"
+
+#include "Python-ast.h"
+#undef Yield /* undefine macro conflicting with winbase.h */
+#include "grammar.h"
+#include "node.h"
+#include "token.h"
+#include "parsetok.h"
+#include "errcode.h"
+#include "code.h"
+#include "symtable.h"
+#include "ast.h"
+#include "marshal.h"
+#include "osdefs.h"
+#include <locale.h>
+
+#ifdef HAVE_SIGNAL_H
+#include <signal.h>
+#endif
+
+#ifdef MS_WINDOWS
+#include "malloc.h" /* for alloca */
+#endif
+
+#ifdef HAVE_LANGINFO_H
+#include <langinfo.h>
+#endif
+
+#ifdef MS_WINDOWS
+#undef BYTE
+#include "windows.h"
+#endif
+
+_Py_IDENTIFIER(flush);
+_Py_IDENTIFIER(name);
+_Py_IDENTIFIER(stdin);
+_Py_IDENTIFIER(stdout);
+_Py_IDENTIFIER(stderr);
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern wchar_t *Py_GetPath(void);
+
+extern grammar _PyParser_Grammar; /* From graminit.c */
+
+/* Forward */
+static void initmain(PyInterpreterState *interp);
+static int initfsencoding(PyInterpreterState *interp);
+static void initsite(void);
+static int initstdio(void);
+static void initsigs(void);
+static void call_py_exitfuncs(void);
+static void wait_for_thread_shutdown(void);
+static void call_ll_exitfuncs(void);
+extern int _PyUnicode_Init(void);
+extern int _PyStructSequence_Init(void);
+extern void _PyUnicode_Fini(void);
+extern int _PyLong_Init(void);
+extern void PyLong_Fini(void);
+extern int _PyFaulthandler_Init(void);
+extern void _PyFaulthandler_Fini(void);
+extern void _PyHash_Fini(void);
+extern int _PyTraceMalloc_Init(void);
+extern int _PyTraceMalloc_Fini(void);
+
+#ifdef WITH_THREAD
+extern void _PyGILState_Init(PyInterpreterState *, PyThreadState *);
+extern void _PyGILState_Fini(void);
+#endif /* WITH_THREAD */
+
+/* Global configuration variable declarations are in pydebug.h */
+/* XXX (ncoghlan): move those declarations to pylifecycle.h? */
+int Py_DebugFlag; /* Needed by parser.c */
+int Py_VerboseFlag; /* Needed by import.c */
+int Py_QuietFlag; /* Needed by sysmodule.c */
+int Py_InteractiveFlag; /* Needed by Py_FdIsInteractive() below */
+int Py_InspectFlag; /* Needed to determine whether to exit at SystemExit */
+int Py_OptimizeFlag = 0; /* Needed by compile.c */
+int Py_NoSiteFlag; /* Suppress 'import site' */
+int Py_BytesWarningFlag; /* Warn on str(bytes) and str(buffer) */
+int Py_UseClassExceptionsFlag = 1; /* Needed by bltinmodule.c: deprecated */
+int Py_FrozenFlag; /* Needed by getpath.c */
+int Py_IgnoreEnvironmentFlag; /* e.g. PYTHONPATH, PYTHONHOME */
+int Py_DontWriteBytecodeFlag; /* Suppress writing bytecode files (*.py[co]) */
+int Py_NoUserSiteDirectory = 0; /* for -s and site.py */
+int Py_UnbufferedStdioFlag = 0; /* Unbuffered binary std{in,out,err} */
+int Py_HashRandomizationFlag = 0; /* for -R and PYTHONHASHSEED */
+int Py_IsolatedFlag = 0; /* for -I, isolate from user's env */
+
+PyThreadState *_Py_Finalizing = 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");
+}
+
+static int initialized = 0;
+
+/* API to access the initialized flag -- useful for esoteric use */
+
+int
+Py_IsInitialized(void)
+{
+ return initialized;
+}
+
+/* Helper to allow an embedding application to override the normal
+ * mechanism that attempts to figure out an appropriate IO encoding
+ */
+
+static char *_Py_StandardStreamEncoding = NULL;
+static char *_Py_StandardStreamErrors = NULL;
+
+int
+Py_SetStandardStreamEncoding(const char *encoding, const char *errors)
+{
+ if (Py_IsInitialized()) {
+ /* This is too late to have any effect */
+ return -1;
+ }
+ /* Can't call PyErr_NoMemory() on errors, as Python hasn't been
+ * initialised yet.
+ *
+ * However, the raw memory allocators are initialised appropriately
+ * as C static variables, so _PyMem_RawStrdup is OK even though
+ * Py_Initialize hasn't been called yet.
+ */
+ if (encoding) {
+ _Py_StandardStreamEncoding = _PyMem_RawStrdup(encoding);
+ if (!_Py_StandardStreamEncoding) {
+ return -2;
+ }
+ }
+ if (errors) {
+ _Py_StandardStreamErrors = _PyMem_RawStrdup(errors);
+ if (!_Py_StandardStreamErrors) {
+ if (_Py_StandardStreamEncoding) {
+ PyMem_RawFree(_Py_StandardStreamEncoding);
+ }
+ return -3;
+ }
+ }
+ return 0;
+}
+
+/* Global initializations. Can be undone by Py_Finalize(). Don't
+ call this twice without an intervening Py_Finalize() 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 int
+add_flag(int flag, const char *envs)
+{
+ int env = atoi(envs);
+ if (flag < env)
+ flag = env;
+ if (flag < 1)
+ flag = 1;
+ return flag;
+}
+
+static char*
+get_codec_name(const char *encoding)
+{
+ char *name_utf8, *name_str;
+ PyObject *codec, *name = NULL;
+
+ codec = _PyCodec_Lookup(encoding);
+ if (!codec)
+ goto error;
+
+ name = _PyObject_GetAttrId(codec, &PyId_name);
+ Py_CLEAR(codec);
+ if (!name)
+ goto error;
+
+ name_utf8 = _PyUnicode_AsString(name);
+ if (name_utf8 == NULL)
+ goto error;
+ name_str = _PyMem_RawStrdup(name_utf8);
+ Py_DECREF(name);
+ if (name_str == NULL) {
+ PyErr_NoMemory();
+ return NULL;
+ }
+ return name_str;
+
+error:
+ Py_XDECREF(codec);
+ Py_XDECREF(name);
+ return NULL;
+}
+
+static char*
+get_locale_encoding(void)
+{
+#ifdef MS_WINDOWS
+ char codepage[100];
+ PyOS_snprintf(codepage, sizeof(codepage), "cp%d", GetACP());
+ return get_codec_name(codepage);
+#elif defined(HAVE_LANGINFO_H) && defined(CODESET)
+ char* codeset = nl_langinfo(CODESET);
+ if (!codeset || codeset[0] == '\0') {
+ PyErr_SetString(PyExc_ValueError, "CODESET is not set or empty");
+ return NULL;
+ }
+ return get_codec_name(codeset);
+#else
+ PyErr_SetNone(PyExc_NotImplementedError);
+ return NULL;
+#endif
+}
+
+static void
+import_init(PyInterpreterState *interp, PyObject *sysmod)
+{
+ PyObject *importlib;
+ PyObject *impmod;
+ PyObject *sys_modules;
+ PyObject *value;
+
+ /* Import _importlib through its frozen version, _frozen_importlib. */
+ if (PyImport_ImportFrozenModule("_frozen_importlib") <= 0) {
+ Py_FatalError("Py_Initialize: can't import _frozen_importlib");
+ }
+ else if (Py_VerboseFlag) {
+ PySys_FormatStderr("import _frozen_importlib # frozen\n");
+ }
+ importlib = PyImport_AddModule("_frozen_importlib");
+ if (importlib == NULL) {
+ Py_FatalError("Py_Initialize: couldn't get _frozen_importlib from "
+ "sys.modules");
+ }
+ interp->importlib = importlib;
+ Py_INCREF(interp->importlib);
+
+ /* Install _importlib as __import__ */
+ impmod = PyInit_imp();
+ if (impmod == NULL) {
+ Py_FatalError("Py_Initialize: can't import imp");
+ }
+ else if (Py_VerboseFlag) {
+ PySys_FormatStderr("import imp # builtin\n");
+ }
+ sys_modules = PyImport_GetModuleDict();
+ if (Py_VerboseFlag) {
+ PySys_FormatStderr("import sys # builtin\n");
+ }
+ if (PyDict_SetItemString(sys_modules, "_imp", impmod) < 0) {
+ Py_FatalError("Py_Initialize: can't save _imp to sys.modules");
+ }
+
+ value = PyObject_CallMethod(importlib, "_install", "OO", sysmod, impmod);
+ if (value == NULL) {
+ PyErr_Print();
+ Py_FatalError("Py_Initialize: importlib install failed");
+ }
+ Py_DECREF(value);
+ Py_DECREF(impmod);
+
+ _PyImportZip_Init();
+}
+
+
+void
+_Py_InitializeEx_Private(int install_sigs, int install_importlib)
+{
+ PyInterpreterState *interp;
+ PyThreadState *tstate;
+ PyObject *bimod, *sysmod, *pstderr;
+ char *p;
+ extern void _Py_ReadyTypes(void);
+
+ if (initialized)
+ return;
+ initialized = 1;
+ _Py_Finalizing = NULL;
+
+#if defined(HAVE_LANGINFO_H) && defined(HAVE_SETLOCALE)
+ /* Set up the LC_CTYPE locale, so we can obtain
+ the locale's charset without having to switch
+ locales. */
+ setlocale(LC_CTYPE, "");
+#endif
+
+ if ((p = Py_GETENV("PYTHONDEBUG")) && *p != '\0')
+ Py_DebugFlag = add_flag(Py_DebugFlag, p);
+ if ((p = Py_GETENV("PYTHONVERBOSE")) && *p != '\0')
+ Py_VerboseFlag = add_flag(Py_VerboseFlag, p);
+ if ((p = Py_GETENV("PYTHONOPTIMIZE")) && *p != '\0')
+ Py_OptimizeFlag = add_flag(Py_OptimizeFlag, p);
+ if ((p = Py_GETENV("PYTHONDONTWRITEBYTECODE")) && *p != '\0')
+ Py_DontWriteBytecodeFlag = add_flag(Py_DontWriteBytecodeFlag, p);
+ /* The variable is only tested for existence here; _PyRandom_Init will
+ check its value further. */
+ if ((p = Py_GETENV("PYTHONHASHSEED")) && *p != '\0')
+ Py_HashRandomizationFlag = add_flag(Py_HashRandomizationFlag, p);
+
+ _PyRandom_Init();
+
+ interp = PyInterpreterState_New();
+ if (interp == NULL)
+ Py_FatalError("Py_Initialize: can't make first interpreter");
+
+ tstate = PyThreadState_New(interp);
+ if (tstate == NULL)
+ Py_FatalError("Py_Initialize: can't make first thread");
+ (void) PyThreadState_Swap(tstate);
+
+#ifdef WITH_THREAD
+ /* We can't call _PyEval_FiniThreads() in Py_Finalize because
+ destroying the GIL might fail when it is being referenced from
+ another running thread (see issue #9901).
+ Instead we destroy the previously created GIL here, which ensures
+ that we can call Py_Initialize / Py_Finalize multiple times. */
+ _PyEval_FiniThreads();
+
+ /* Auto-thread-state API */
+ _PyGILState_Init(interp, tstate);
+#endif /* WITH_THREAD */
+
+ _Py_ReadyTypes();
+
+ if (!_PyFrame_Init())
+ Py_FatalError("Py_Initialize: can't init frames");
+
+ if (!_PyLong_Init())
+ Py_FatalError("Py_Initialize: can't init longs");
+
+ if (!PyByteArray_Init())
+ Py_FatalError("Py_Initialize: can't init bytearray");
+
+ if (!_PyFloat_Init())
+ Py_FatalError("Py_Initialize: can't init float");
+
+ interp->modules = PyDict_New();
+ if (interp->modules == NULL)
+ Py_FatalError("Py_Initialize: can't make modules dictionary");
+
+ /* Init Unicode implementation; relies on the codec registry */
+ if (_PyUnicode_Init() < 0)
+ Py_FatalError("Py_Initialize: can't initialize unicode");
+ if (_PyStructSequence_Init() < 0)
+ Py_FatalError("Py_Initialize: can't initialize structseq");
+
+ bimod = _PyBuiltin_Init();
+ if (bimod == NULL)
+ Py_FatalError("Py_Initialize: can't initialize builtins modules");
+ _PyImport_FixupBuiltin(bimod, "builtins");
+ interp->builtins = PyModule_GetDict(bimod);
+ if (interp->builtins == NULL)
+ Py_FatalError("Py_Initialize: can't initialize builtins dict");
+ Py_INCREF(interp->builtins);
+
+ /* initialize builtin exceptions */
+ _PyExc_Init(bimod);
+
+ sysmod = _PySys_Init();
+ if (sysmod == NULL)
+ Py_FatalError("Py_Initialize: can't initialize sys");
+ interp->sysdict = PyModule_GetDict(sysmod);
+ if (interp->sysdict == NULL)
+ Py_FatalError("Py_Initialize: can't initialize sys dict");
+ Py_INCREF(interp->sysdict);
+ _PyImport_FixupBuiltin(sysmod, "sys");
+ PySys_SetPath(Py_GetPath());
+ PyDict_SetItemString(interp->sysdict, "modules",
+ interp->modules);
+
+ /* Set up a preliminary stderr printer until we have enough
+ infrastructure for the io module in place. */
+ pstderr = PyFile_NewStdPrinter(fileno(stderr));
+ if (pstderr == NULL)
+ Py_FatalError("Py_Initialize: can't set preliminary stderr");
+ _PySys_SetObjectId(&PyId_stderr, pstderr);
+ PySys_SetObject("__stderr__", pstderr);
+ Py_DECREF(pstderr);
+
+ _PyImport_Init();
+
+ _PyImportHooks_Init();
+
+ /* Initialize _warnings. */
+ _PyWarnings_Init();
+
+ if (!install_importlib)
+ return;
+
+ import_init(interp, sysmod);
+
+ /* initialize the faulthandler module */
+ if (_PyFaulthandler_Init())
+ Py_FatalError("Py_Initialize: can't initialize faulthandler");
+
+ if (_PyTime_Init() < 0)
+ Py_FatalError("Py_Initialize: can't initialize time");
+
+ if (initfsencoding(interp) < 0)
+ Py_FatalError("Py_Initialize: unable to load the file system codec");
+
+ if (install_sigs)
+ initsigs(); /* Signal handling stuff, including initintr() */
+
+ if (_PyTraceMalloc_Init() < 0)
+ Py_FatalError("Py_Initialize: can't initialize tracemalloc");
+
+ initmain(interp); /* Module __main__ */
+ if (initstdio() < 0)
+ Py_FatalError(
+ "Py_Initialize: can't initialize sys standard streams");
+
+ /* Initialize warnings. */
+ if (PySys_HasWarnOptions()) {
+ PyObject *warnings_module = PyImport_ImportModule("warnings");
+ if (warnings_module == NULL) {
+ fprintf(stderr, "'import warnings' failed; traceback:\n");
+ PyErr_Print();
+ }
+ Py_XDECREF(warnings_module);
+ }
+
+ if (!Py_NoSiteFlag)
+ initsite(); /* Module site */
+}
+
+void
+Py_InitializeEx(int install_sigs)
+{
+ _Py_InitializeEx_Private(install_sigs, 1);
+}
+
+void
+Py_Initialize(void)
+{
+ Py_InitializeEx(1);
+}
+
+
+#ifdef COUNT_ALLOCS
+extern void dump_counts(FILE*);
+#endif
+
+/* 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 void
+flush_std_files(void)
+{
+ PyObject *fout = _PySys_GetObjectId(&PyId_stdout);
+ PyObject *ferr = _PySys_GetObjectId(&PyId_stderr);
+ PyObject *tmp;
+
+ if (fout != NULL && fout != Py_None && !file_is_closed(fout)) {
+ tmp = _PyObject_CallMethodId(fout, &PyId_flush, "");
+ if (tmp == NULL)
+ PyErr_WriteUnraisable(fout);
+ else
+ Py_DECREF(tmp);
+ }
+
+ if (ferr != NULL && ferr != Py_None && !file_is_closed(ferr)) {
+ tmp = _PyObject_CallMethodId(ferr, &PyId_flush, "");
+ if (tmp == NULL)
+ PyErr_Clear();
+ else
+ Py_DECREF(tmp);
+ }
+}
+
+/* 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.
+
+*/
+
+void
+Py_Finalize(void)
+{
+ PyInterpreterState *interp;
+ PyThreadState *tstate;
+
+ if (!initialized)
+ return;
+
+ wait_for_thread_shutdown();
+
+ /* 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
+ * interpreter 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.
+ */
+ call_py_exitfuncs();
+
+ /* Get current thread state and interpreter pointer */
+ tstate = PyThreadState_GET();
+ interp = tstate->interp;
+
+ /* Remaining threads (e.g. daemon threads) will automatically exit
+ after taking the GIL (in PyEval_RestoreThread()). */
+ _Py_Finalizing = tstate;
+ initialized = 0;
+
+ /* Flush stdout+stderr */
+ flush_std_files();
+
+ /* 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_Collect();
+#ifdef COUNT_ALLOCS
+ /* With COUNT_ALLOCS, it helps to run GC multiple times:
+ each collection might release some types from the type
+ list, so they become garbage. */
+ while (PyGC_Collect() > 0)
+ /* nothing */;
+#endif
+ /* Destroy all modules */
+ PyImport_Cleanup();
+
+ /* Flush stdout+stderr (again, in case more was printed) */
+ flush_std_files();
+
+ /* 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_Collect();
+#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();
+
+ /* Debugging stuff */
+#ifdef COUNT_ALLOCS
+ dump_counts(stdout);
+#endif
+ /* dump hash stats */
+ _PyHash_Fini();
+
+ _PY_DEBUG_PRINT_TOTAL_REFS();
+
+#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 (Py_GETENV("PYTHONDUMPREFS"))
+ _Py_PrintReferences(stderr);
+#endif /* Py_TRACE_REFS */
+
+ /* Clear interpreter state and all thread states. */
+ PyInterpreterState_Clear(interp);
+
+ /* Now we decref the exception classes. After this point nothing
+ can raise an exception. That's okay, because each Fini() method
+ below has been checked to make sure no exceptions are ever
+ raised.
+ */
+
+ _PyExc_Fini();
+
+ /* Sundry finalizers */
+ PyMethod_Fini();
+ PyFrame_Fini();
+ PyCFunction_Fini();
+ PyTuple_Fini();
+ PyList_Fini();
+ PySet_Fini();
+ PyBytes_Fini();
+ PyByteArray_Fini();
+ PyLong_Fini();
+ PyFloat_Fini();
+ PyDict_Fini();
+ PySlice_Fini();
+ _PyGC_Fini();
+ _PyRandom_Fini();
+
+ /* Cleanup Unicode implementation */
+ _PyUnicode_Fini();
+
+ /* reset file system default encoding */
+ if (!Py_HasFileSystemDefaultEncoding && Py_FileSystemDefaultEncoding) {
+ PyMem_RawFree((char*)Py_FileSystemDefaultEncoding);
+ Py_FileSystemDefaultEncoding = NULL;
+ }
+
+ /* XXX Still allocated:
+ - various static ad-hoc pointers to interned strings
+ - int and float free list blocks
+ - whatever various modules and libraries allocate
+ */
+
+ PyGrammar_RemoveAccelerators(&_PyParser_Grammar);
+
+ /* Cleanup auto-thread-state */
+#ifdef WITH_THREAD
+ _PyGILState_Fini();
+#endif /* WITH_THREAD */
+
+ /* Delete current thread. After this, many C API calls become crashy. */
+ PyThreadState_Swap(NULL);
+ PyInterpreterState_Delete(interp);
+
+#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 (Py_GETENV("PYTHONDUMPREFS"))
+ _Py_PrintReferenceAddresses(stderr);
+#endif /* Py_TRACE_REFS */
+#ifdef PYMALLOC_DEBUG
+ if (Py_GETENV("PYTHONMALLOCSTATS"))
+ _PyObject_DebugMallocStats(stderr);
+#endif
+
+ call_ll_exitfuncs();
+}
+
+/* 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.
+
+*/
+
+PyThreadState *
+Py_NewInterpreter(void)
+{
+ PyInterpreterState *interp;
+ PyThreadState *tstate, *save_tstate;
+ PyObject *bimod, *sysmod;
+
+ if (!initialized)
+ Py_FatalError("Py_NewInterpreter: call Py_Initialize first");
+
+ interp = PyInterpreterState_New();
+ if (interp == NULL)
+ return NULL;
+
+ tstate = PyThreadState_New(interp);
+ if (tstate == NULL) {
+ PyInterpreterState_Delete(interp);
+ return NULL;
+ }
+
+ save_tstate = PyThreadState_Swap(tstate);
+
+ /* XXX The following is lax in error checking */
+
+ interp->modules = PyDict_New();
+
+ bimod = _PyImport_FindBuiltin("builtins");
+ if (bimod != NULL) {
+ interp->builtins = PyModule_GetDict(bimod);
+ if (interp->builtins == NULL)
+ goto handle_error;
+ Py_INCREF(interp->builtins);
+ }
+
+ /* initialize builtin exceptions */
+ _PyExc_Init(bimod);
+
+ sysmod = _PyImport_FindBuiltin("sys");
+ if (bimod != NULL && sysmod != NULL) {
+ PyObject *pstderr;
+
+ interp->sysdict = PyModule_GetDict(sysmod);
+ if (interp->sysdict == NULL)
+ goto handle_error;
+ Py_INCREF(interp->sysdict);
+ PySys_SetPath(Py_GetPath());
+ PyDict_SetItemString(interp->sysdict, "modules",
+ interp->modules);
+ /* Set up a preliminary stderr printer until we have enough
+ infrastructure for the io module in place. */
+ pstderr = PyFile_NewStdPrinter(fileno(stderr));
+ if (pstderr == NULL)
+ Py_FatalError("Py_Initialize: can't set preliminary stderr");
+ _PySys_SetObjectId(&PyId_stderr, pstderr);
+ PySys_SetObject("__stderr__", pstderr);
+ Py_DECREF(pstderr);
+
+ _PyImportHooks_Init();
+
+ import_init(interp, sysmod);
+
+ if (initfsencoding(interp) < 0)
+ goto handle_error;
+
+ if (initstdio() < 0)
+ Py_FatalError(
+ "Py_Initialize: can't initialize sys standard streams");
+ initmain(interp);
+ if (!Py_NoSiteFlag)
+ initsite();
+ }
+
+ if (!PyErr_Occurred())
+ return tstate;
+
+handle_error:
+ /* Oops, it didn't work. Undo it all. */
+
+ PyErr_PrintEx(0);
+ PyThreadState_Clear(tstate);
+ PyThreadState_Swap(save_tstate);
+ PyThreadState_Delete(tstate);
+ PyInterpreterState_Delete(interp);
+
+ return NULL;
+}
+
+/* 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_Finalize() 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("Py_EndInterpreter: thread is not current");
+ if (tstate->frame != NULL)
+ Py_FatalError("Py_EndInterpreter: thread still has a frame");
+
+ wait_for_thread_shutdown();
+
+ if (tstate != interp->tstate_head || tstate->next != NULL)
+ Py_FatalError("Py_EndInterpreter: not the last thread");
+
+ PyImport_Cleanup();
+ PyInterpreterState_Clear(interp);
+ PyThreadState_Swap(NULL);
+ PyInterpreterState_Delete(interp);
+}
+
+#ifdef MS_WINDOWS
+static wchar_t *progname = L"python";
+#else
+static wchar_t *progname = L"python3";
+#endif
+
+void
+Py_SetProgramName(wchar_t *pn)
+{
+ if (pn && *pn)
+ progname = pn;
+}
+
+wchar_t *
+Py_GetProgramName(void)
+{
+ return progname;
+}
+
+static wchar_t *default_home = NULL;
+static wchar_t env_home[MAXPATHLEN+1];
+
+void
+Py_SetPythonHome(wchar_t *home)
+{
+ default_home = home;
+}
+
+wchar_t *
+Py_GetPythonHome(void)
+{
+ wchar_t *home = default_home;
+ if (home == NULL && !Py_IgnoreEnvironmentFlag) {
+ char* chome = Py_GETENV("PYTHONHOME");
+ if (chome) {
+ size_t size = Py_ARRAY_LENGTH(env_home);
+ size_t r = mbstowcs(env_home, chome, size);
+ if (r != (size_t)-1 && r < size)
+ home = env_home;
+ }
+
+ }
+ return home;
+}
+
+/* Create __main__ module */
+
+static void
+initmain(PyInterpreterState *interp)
+{
+ PyObject *m, *d, *loader;
+ m = PyImport_AddModule("__main__");
+ if (m == NULL)
+ Py_FatalError("can't create __main__ module");
+ d = PyModule_GetDict(m);
+ if (PyDict_GetItemString(d, "__builtins__") == NULL) {
+ PyObject *bimod = PyImport_ImportModule("builtins");
+ if (bimod == NULL) {
+ Py_FatalError("Failed to retrieve builtins module");
+ }
+ if (PyDict_SetItemString(d, "__builtins__", bimod) < 0) {
+ Py_FatalError("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_FatalError("Failed to retrieve BuiltinImporter");
+ }
+ if (PyDict_SetItemString(d, "__loader__", loader) < 0) {
+ Py_FatalError("Failed to initialize __main__.__loader__");
+ }
+ Py_DECREF(loader);
+ }
+}
+
+static int
+initfsencoding(PyInterpreterState *interp)
+{
+ PyObject *codec;
+
+ if (Py_FileSystemDefaultEncoding == NULL)
+ {
+ Py_FileSystemDefaultEncoding = get_locale_encoding();
+ if (Py_FileSystemDefaultEncoding == NULL)
+ Py_FatalError("Py_Initialize: Unable to get the locale encoding");
+
+ Py_HasFileSystemDefaultEncoding = 0;
+ interp->fscodec_initialized = 1;
+ return 0;
+ }
+
+ /* the encoding is mbcs, utf-8 or ascii */
+ codec = _PyCodec_Lookup(Py_FileSystemDefaultEncoding);
+ if (!codec) {
+ /* Such error can only occurs in critical situations: no more
+ * memory, import a module of the standard library failed,
+ * etc. */
+ return -1;
+ }
+ Py_DECREF(codec);
+ interp->fscodec_initialized = 1;
+ return 0;
+}
+
+/* Import the site module (not into __main__ though) */
+
+static void
+initsite(void)
+{
+ PyObject *m;
+ m = PyImport_ImportModule("site");
+ if (m == NULL) {
+ fprintf(stderr, "Failed to import the site module\n");
+ PyErr_Print();
+ Py_Finalize();
+ exit(1);
+ }
+ else {
+ Py_DECREF(m);
+ }
+}
+
+static PyObject*
+create_stdio(PyObject* io,
+ int fd, int write_mode, char* name,
+ char* encoding, char* errors)
+{
+ PyObject *buf = NULL, *stream = NULL, *text = NULL, *raw = NULL, *res;
+ const char* mode;
+ const char* newline;
+ PyObject *line_buffering;
+ int buffering, isatty;
+ _Py_IDENTIFIER(open);
+ _Py_IDENTIFIER(isatty);
+ _Py_IDENTIFIER(TextIOWrapper);
+ _Py_IDENTIFIER(mode);
+
+ /* 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 (Py_UnbufferedStdioFlag && write_mode)
+ buffering = 0;
+ else
+ buffering = -1;
+ if (write_mode)
+ mode = "wb";
+ else
+ mode = "rb";
+ buf = _PyObject_CallMethodId(io, &PyId_open, "isiOOOi",
+ fd, mode, buffering,
+ Py_None, Py_None, Py_None, 0);
+ 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);
+ }
+
+ text = PyUnicode_FromString(name);
+ if (text == NULL || _PyObject_SetAttrId(raw, &PyId_name, text) < 0)
+ goto error;
+ res = _PyObject_CallMethodId(raw, &PyId_isatty, "");
+ if (res == NULL)
+ goto error;
+ isatty = PyObject_IsTrue(res);
+ Py_DECREF(res);
+ if (isatty == -1)
+ goto error;
+ if (isatty || Py_UnbufferedStdioFlag)
+ 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
+
+ stream = _PyObject_CallMethodId(io, &PyId_TextIOWrapper, "OsssO",
+ buf, encoding, errors,
+ newline, line_buffering);
+ Py_CLEAR(buf);
+ 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);
+ return NULL;
+}
+
+static int
+is_valid_fd(int fd)
+{
+ int dummy_fd;
+ if (fd < 0 || !_PyVerify_fd(fd))
+ return 0;
+ dummy_fd = dup(fd);
+ if (dummy_fd < 0)
+ return 0;
+ close(dummy_fd);
+ return 1;
+}
+
+/* Initialize sys.stdin, stdout, stderr and builtins.open */
+static int
+initstdio(void)
+{
+ PyObject *iomod = NULL, *wrapper;
+ PyObject *bimod = NULL;
+ PyObject *m;
+ PyObject *std = NULL;
+ int status = 0, fd;
+ PyObject * encoding_attr;
+ char *pythonioencoding = NULL, *encoding, *errors;
+
+ /* 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 (!(bimod = PyImport_ImportModule("builtins"))) {
+ goto error;
+ }
+
+ if (!(iomod = PyImport_ImportModule("io"))) {
+ goto error;
+ }
+ if (!(wrapper = PyObject_GetAttrString(iomod, "OpenWrapper"))) {
+ goto error;
+ }
+
+ /* Set builtins.open */
+ if (PyObject_SetAttrString(bimod, "open", wrapper) == -1) {
+ Py_DECREF(wrapper);
+ goto error;
+ }
+ Py_DECREF(wrapper);
+
+ encoding = _Py_StandardStreamEncoding;
+ errors = _Py_StandardStreamErrors;
+ if (!encoding || !errors) {
+ if (!errors) {
+ /* When the LC_CTYPE locale is the POSIX locale ("C locale"),
+ stdin and stdout use the surrogateescape error handler by
+ default, instead of the strict error handler. */
+ char *loc = setlocale(LC_CTYPE, NULL);
+ if (loc != NULL && strcmp(loc, "C") == 0)
+ errors = "surrogateescape";
+ }
+
+ pythonioencoding = Py_GETENV("PYTHONIOENCODING");
+ if (pythonioencoding) {
+ char *err;
+ pythonioencoding = _PyMem_Strdup(pythonioencoding);
+ if (pythonioencoding == NULL) {
+ PyErr_NoMemory();
+ goto error;
+ }
+ err = strchr(pythonioencoding, ':');
+ if (err) {
+ *err = '\0';
+ err++;
+ if (*err && !_Py_StandardStreamErrors) {
+ errors = err;
+ }
+ }
+ if (*pythonioencoding && !encoding) {
+ encoding = pythonioencoding;
+ }
+ }
+ }
+
+ /* 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.
+ */
+ if (!is_valid_fd(fd)) {
+ std = Py_None;
+ Py_INCREF(std);
+ }
+ else {
+ std = create_stdio(iomod, fd, 0, "<stdin>", encoding, errors);
+ if (std == NULL)
+ goto error;
+ } /* if (fd < 0) */
+ PySys_SetObject("__stdin__", std);
+ _PySys_SetObjectId(&PyId_stdin, std);
+ Py_DECREF(std);
+
+ /* Set sys.stdout */
+ fd = fileno(stdout);
+ if (!is_valid_fd(fd)) {
+ std = Py_None;
+ Py_INCREF(std);
+ }
+ else {
+ std = create_stdio(iomod, fd, 1, "<stdout>", encoding, errors);
+ if (std == NULL)
+ goto error;
+ } /* if (fd < 0) */
+ 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 (!is_valid_fd(fd)) {
+ std = Py_None;
+ Py_INCREF(std);
+ }
+ else {
+ std = create_stdio(iomod, fd, 1, "<stderr>", encoding, "backslashreplace");
+ if (std == NULL)
+ goto error;
+ } /* if (fd < 0) */
+
+ /* 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;
+ std_encoding = _PyUnicode_AsString(encoding_attr);
+ if (std_encoding != NULL) {
+ PyObject *codec_info = _PyCodec_Lookup(std_encoding);
+ Py_XDECREF(codec_info);
+ }
+ Py_DECREF(encoding_attr);
+ }
+ PyErr_Clear(); /* 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
+
+ if (0) {
+ error:
+ status = -1;
+ }
+
+ /* We won't need them anymore. */
+ if (_Py_StandardStreamEncoding) {
+ PyMem_RawFree(_Py_StandardStreamEncoding);
+ _Py_StandardStreamEncoding = NULL;
+ }
+ if (_Py_StandardStreamErrors) {
+ PyMem_RawFree(_Py_StandardStreamErrors);
+ _Py_StandardStreamErrors = NULL;
+ }
+ PyMem_Free(pythonioencoding);
+ Py_XDECREF(bimod);
+ Py_XDECREF(iomod);
+ return status;
+}
+
+
+/* Print fatal error message and abort */
+
+void
+Py_FatalError(const char *msg)
+{
+ const int fd = fileno(stderr);
+ PyThreadState *tstate;
+
+ fprintf(stderr, "Fatal Python error: %s\n", msg);
+ fflush(stderr); /* it helps in Windows debug build */
+ if (PyErr_Occurred()) {
+ PyErr_PrintEx(0);
+ }
+ else {
+ tstate = _Py_atomic_load_relaxed(&_PyThreadState_Current);
+ if (tstate != NULL) {
+ fputc('\n', stderr);
+ fflush(stderr);
+ _Py_DumpTracebackThreads(fd, tstate->interp, tstate);
+ }
+ _PyFaulthandler_Fini();
+ }
+
+#ifdef MS_WINDOWS
+ {
+ size_t len = strlen(msg);
+ WCHAR* buffer;
+ size_t i;
+
+ /* 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. */
+ buffer = alloca( (len+1) * (sizeof *buffer));
+ for( i=0; i<=len; ++i)
+ buffer[i] = msg[i];
+ OutputDebugStringW(L"Fatal Python error: ");
+ OutputDebugStringW(buffer);
+ OutputDebugStringW(L"\n");
+ }
+#ifdef _DEBUG
+ DebugBreak();
+#endif
+#endif /* MS_WINDOWS */
+ abort();
+}
+
+/* Clean up and exit */
+
+#ifdef WITH_THREAD
+#include "pythread.h"
+#endif
+
+static void (*pyexitfunc)(void) = NULL;
+/* For the atexit module. */
+void _Py_PyAtExit(void (*func)(void))
+{
+ pyexitfunc = func;
+}
+
+static void
+call_py_exitfuncs(void)
+{
+ if (pyexitfunc == NULL)
+ return;
+
+ (*pyexitfunc)();
+ PyErr_Clear();
+}
+
+/* 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(void)
+{
+#ifdef WITH_THREAD
+ _Py_IDENTIFIER(_shutdown);
+ PyObject *result;
+ PyThreadState *tstate = PyThreadState_GET();
+ PyObject *threading = PyMapping_GetItemString(tstate->interp->modules,
+ "threading");
+ if (threading == NULL) {
+ /* threading not imported */
+ PyErr_Clear();
+ return;
+ }
+ result = _PyObject_CallMethodId(threading, &PyId__shutdown, "");
+ if (result == NULL) {
+ PyErr_WriteUnraisable(threading);
+ }
+ else {
+ Py_DECREF(result);
+ }
+ Py_DECREF(threading);
+#endif
+}
+
+#define NEXITFUNCS 32
+static void (*exitfuncs[NEXITFUNCS])(void);
+static int nexitfuncs = 0;
+
+int Py_AtExit(void (*func)(void))
+{
+ if (nexitfuncs >= NEXITFUNCS)
+ return -1;
+ exitfuncs[nexitfuncs++] = func;
+ return 0;
+}
+
+static void
+call_ll_exitfuncs(void)
+{
+ while (nexitfuncs > 0)
+ (*exitfuncs[--nexitfuncs])();
+
+ fflush(stdout);
+ fflush(stderr);
+}
+
+void
+Py_Exit(int sts)
+{
+ Py_Finalize();
+
+ exit(sts);
+}
+
+static void
+initsigs(void)
+{
+#ifdef SIGPIPE
+ PyOS_setsig(SIGPIPE, SIG_IGN);
+#endif
+#ifdef SIGXFZ
+ PyOS_setsig(SIGXFZ, SIG_IGN);
+#endif
+#ifdef SIGXFSZ
+ PyOS_setsig(SIGXFSZ, SIG_IGN);
+#endif
+ PyOS_InitInterrupts(); /* May imply initsignal() */
+ if (PyErr_Occurred()) {
+ Py_FatalError("Py_Initialize: can't import signal");
+ }
+}
+
+
+/* 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.
+ */
+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);
+}
+
+
+#if defined(USE_STACKCHECK)
+#if defined(WIN32) && defined(_MSC_VER)
+
+/* Stack checking for Microsoft C */
+
+#include <malloc.h>
+#include <excpt.h>
+
+/*
+ * Return non-zero when we run out of memory on the stack; zero otherwise.
+ */
+int
+PyOS_CheckStack(void)
+{
+ __try {
+ /* alloca throws a stack overflow exception if there's
+ not enough space left on the stack */
+ alloca(PYOS_STACK_MARGIN * sizeof(void*));
+ return 0;
+ } __except (GetExceptionCode() == STATUS_STACK_OVERFLOW ?
+ EXCEPTION_EXECUTE_HANDLER :
+ EXCEPTION_CONTINUE_SEARCH) {
+ int errcode = _resetstkoflw();
+ if (errcode == 0)
+ {
+ Py_FatalError("Could not reset the stack!");
+ }
+ }
+ return 1;
+}
+
+#endif /* WIN32 && _MSC_VER */
+
+/* Alternate implementations can be added here... */
+
+#endif /* USE_STACKCHECK */
+
+
+/* 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
diff --git a/Python/pythonrun.c b/Python/pythonrun.c
index b5707c4..992a5a3 100644
--- a/Python/pythonrun.c
+++ b/Python/pythonrun.c
@@ -40,7 +40,6 @@ _Py_IDENTIFIER(flush);
_Py_IDENTIFIER(last_traceback);
_Py_IDENTIFIER(last_type);
_Py_IDENTIFIER(last_value);
-_Py_IDENTIFIER(name);
_Py_IDENTIFIER(ps1);
_Py_IDENTIFIER(ps2);
_Py_IDENTIFIER(stdin);
@@ -48,43 +47,13 @@ _Py_IDENTIFIER(stdout);
_Py_IDENTIFIER(stderr);
_Py_static_string(PyId_string, "<string>");
-#ifdef Py_REF_DEBUG
-static
-void _print_total_refs(void) {
- PyObject *xoptions, *value;
- _Py_IDENTIFIER(showrefcount);
-
- xoptions = PySys_GetXOptions();
- if (xoptions == NULL)
- return;
- value = _PyDict_GetItemId(xoptions, &PyId_showrefcount);
- if (value == Py_True)
- fprintf(stderr,
- "[%" PY_FORMAT_SIZE_T "d refs, "
- "%" PY_FORMAT_SIZE_T "d blocks]\n",
- _Py_GetRefTotal(), _Py_GetAllocatedBlocks());
-}
-#endif
-
-#ifndef Py_REF_DEBUG
-#define PRINT_TOTAL_REFS()
-#else /* Py_REF_DEBUG */
-#define PRINT_TOTAL_REFS() _print_total_refs()
-#endif
-
#ifdef __cplusplus
extern "C" {
#endif
-extern wchar_t *Py_GetPath(void);
-
extern grammar _PyParser_Grammar; /* From graminit.c */
/* Forward */
-static void initmain(PyInterpreterState *interp);
-static int initfsencoding(PyInterpreterState *interp);
-static void initsite(void);
-static int initstdio(void);
static void flush_io(void);
static PyObject *run_mod(mod_ty, PyObject *, PyObject *, PyObject *,
PyCompilerFlags *, PyArena *);
@@ -92,1192 +61,6 @@ static PyObject *run_pyc_file(FILE *, const char *, PyObject *, PyObject *,
PyCompilerFlags *);
static void err_input(perrdetail *);
static void err_free(perrdetail *);
-static void initsigs(void);
-static void call_py_exitfuncs(void);
-static void wait_for_thread_shutdown(void);
-static void call_ll_exitfuncs(void);
-extern int _PyUnicode_Init(void);
-extern int _PyStructSequence_Init(void);
-extern void _PyUnicode_Fini(void);
-extern int _PyLong_Init(void);
-extern void PyLong_Fini(void);
-extern int _PyFaulthandler_Init(void);
-extern void _PyFaulthandler_Fini(void);
-extern void _PyHash_Fini(void);
-extern int _PyTraceMalloc_Init(void);
-extern int _PyTraceMalloc_Fini(void);
-
-#ifdef WITH_THREAD
-extern void _PyGILState_Init(PyInterpreterState *, PyThreadState *);
-extern void _PyGILState_Fini(void);
-#endif /* WITH_THREAD */
-
-int Py_DebugFlag; /* Needed by parser.c */
-int Py_VerboseFlag; /* Needed by import.c */
-int Py_QuietFlag; /* Needed by sysmodule.c */
-int Py_InteractiveFlag; /* Needed by Py_FdIsInteractive() below */
-int Py_InspectFlag; /* Needed to determine whether to exit at SystemExit */
-int Py_NoSiteFlag; /* Suppress 'import site' */
-int Py_BytesWarningFlag; /* Warn on str(bytes) and str(buffer) */
-int Py_DontWriteBytecodeFlag; /* Suppress writing bytecode files (*.py[co]) */
-int Py_UseClassExceptionsFlag = 1; /* Needed by bltinmodule.c: deprecated */
-int Py_FrozenFlag; /* Needed by getpath.c */
-int Py_IgnoreEnvironmentFlag; /* e.g. PYTHONPATH, PYTHONHOME */
-int Py_NoUserSiteDirectory = 0; /* for -s and site.py */
-int Py_UnbufferedStdioFlag = 0; /* Unbuffered binary std{in,out,err} */
-int Py_HashRandomizationFlag = 0; /* for -R and PYTHONHASHSEED */
-int Py_IsolatedFlag = 0; /* for -I, isolate from user's env */
-
-PyThreadState *_Py_Finalizing = 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");
-}
-
-static int initialized = 0;
-
-/* API to access the initialized flag -- useful for esoteric use */
-
-int
-Py_IsInitialized(void)
-{
- return initialized;
-}
-
-/* Helper to allow an embedding application to override the normal
- * mechanism that attempts to figure out an appropriate IO encoding
- */
-
-static char *_Py_StandardStreamEncoding = NULL;
-static char *_Py_StandardStreamErrors = NULL;
-
-int
-Py_SetStandardStreamEncoding(const char *encoding, const char *errors)
-{
- if (Py_IsInitialized()) {
- /* This is too late to have any effect */
- return -1;
- }
- /* Can't call PyErr_NoMemory() on errors, as Python hasn't been
- * initialised yet.
- *
- * However, the raw memory allocators are initialised appropriately
- * as C static variables, so _PyMem_RawStrdup is OK even though
- * Py_Initialize hasn't been called yet.
- */
- if (encoding) {
- _Py_StandardStreamEncoding = _PyMem_RawStrdup(encoding);
- if (!_Py_StandardStreamEncoding) {
- return -2;
- }
- }
- if (errors) {
- _Py_StandardStreamErrors = _PyMem_RawStrdup(errors);
- if (!_Py_StandardStreamErrors) {
- if (_Py_StandardStreamEncoding) {
- PyMem_RawFree(_Py_StandardStreamEncoding);
- }
- return -3;
- }
- }
- return 0;
-}
-
-/* Global initializations. Can be undone by Py_Finalize(). Don't
- call this twice without an intervening Py_Finalize() 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 int
-add_flag(int flag, const char *envs)
-{
- int env = atoi(envs);
- if (flag < env)
- flag = env;
- if (flag < 1)
- flag = 1;
- return flag;
-}
-
-static char*
-get_codec_name(const char *encoding)
-{
- char *name_utf8, *name_str;
- PyObject *codec, *name = NULL;
-
- codec = _PyCodec_Lookup(encoding);
- if (!codec)
- goto error;
-
- name = _PyObject_GetAttrId(codec, &PyId_name);
- Py_CLEAR(codec);
- if (!name)
- goto error;
-
- name_utf8 = _PyUnicode_AsString(name);
- if (name_utf8 == NULL)
- goto error;
- name_str = _PyMem_RawStrdup(name_utf8);
- Py_DECREF(name);
- if (name_str == NULL) {
- PyErr_NoMemory();
- return NULL;
- }
- return name_str;
-
-error:
- Py_XDECREF(codec);
- Py_XDECREF(name);
- return NULL;
-}
-
-static char*
-get_locale_encoding(void)
-{
-#ifdef MS_WINDOWS
- char codepage[100];
- PyOS_snprintf(codepage, sizeof(codepage), "cp%d", GetACP());
- return get_codec_name(codepage);
-#elif defined(HAVE_LANGINFO_H) && defined(CODESET)
- char* codeset = nl_langinfo(CODESET);
- if (!codeset || codeset[0] == '\0') {
- PyErr_SetString(PyExc_ValueError, "CODESET is not set or empty");
- return NULL;
- }
- return get_codec_name(codeset);
-#else
- PyErr_SetNone(PyExc_NotImplementedError);
- return NULL;
-#endif
-}
-
-static void
-import_init(PyInterpreterState *interp, PyObject *sysmod)
-{
- PyObject *importlib;
- PyObject *impmod;
- PyObject *sys_modules;
- PyObject *value;
-
- /* Import _importlib through its frozen version, _frozen_importlib. */
- if (PyImport_ImportFrozenModule("_frozen_importlib") <= 0) {
- Py_FatalError("Py_Initialize: can't import _frozen_importlib");
- }
- else if (Py_VerboseFlag) {
- PySys_FormatStderr("import _frozen_importlib # frozen\n");
- }
- importlib = PyImport_AddModule("_frozen_importlib");
- if (importlib == NULL) {
- Py_FatalError("Py_Initialize: couldn't get _frozen_importlib from "
- "sys.modules");
- }
- interp->importlib = importlib;
- Py_INCREF(interp->importlib);
-
- /* Install _importlib as __import__ */
- impmod = PyInit_imp();
- if (impmod == NULL) {
- Py_FatalError("Py_Initialize: can't import imp");
- }
- else if (Py_VerboseFlag) {
- PySys_FormatStderr("import imp # builtin\n");
- }
- sys_modules = PyImport_GetModuleDict();
- if (Py_VerboseFlag) {
- PySys_FormatStderr("import sys # builtin\n");
- }
- if (PyDict_SetItemString(sys_modules, "_imp", impmod) < 0) {
- Py_FatalError("Py_Initialize: can't save _imp to sys.modules");
- }
-
- value = PyObject_CallMethod(importlib, "_install", "OO", sysmod, impmod);
- if (value == NULL) {
- PyErr_Print();
- Py_FatalError("Py_Initialize: importlib install failed");
- }
- Py_DECREF(value);
- Py_DECREF(impmod);
-
- _PyImportZip_Init();
-}
-
-
-void
-_Py_InitializeEx_Private(int install_sigs, int install_importlib)
-{
- PyInterpreterState *interp;
- PyThreadState *tstate;
- PyObject *bimod, *sysmod, *pstderr;
- char *p;
- extern void _Py_ReadyTypes(void);
-
- if (initialized)
- return;
- initialized = 1;
- _Py_Finalizing = NULL;
-
-#if defined(HAVE_LANGINFO_H) && defined(HAVE_SETLOCALE)
- /* Set up the LC_CTYPE locale, so we can obtain
- the locale's charset without having to switch
- locales. */
- setlocale(LC_CTYPE, "");
-#endif
-
- if ((p = Py_GETENV("PYTHONDEBUG")) && *p != '\0')
- Py_DebugFlag = add_flag(Py_DebugFlag, p);
- if ((p = Py_GETENV("PYTHONVERBOSE")) && *p != '\0')
- Py_VerboseFlag = add_flag(Py_VerboseFlag, p);
- if ((p = Py_GETENV("PYTHONOPTIMIZE")) && *p != '\0')
- Py_OptimizeFlag = add_flag(Py_OptimizeFlag, p);
- if ((p = Py_GETENV("PYTHONDONTWRITEBYTECODE")) && *p != '\0')
- Py_DontWriteBytecodeFlag = add_flag(Py_DontWriteBytecodeFlag, p);
- /* The variable is only tested for existence here; _PyRandom_Init will
- check its value further. */
- if ((p = Py_GETENV("PYTHONHASHSEED")) && *p != '\0')
- Py_HashRandomizationFlag = add_flag(Py_HashRandomizationFlag, p);
-
- _PyRandom_Init();
-
- interp = PyInterpreterState_New();
- if (interp == NULL)
- Py_FatalError("Py_Initialize: can't make first interpreter");
-
- tstate = PyThreadState_New(interp);
- if (tstate == NULL)
- Py_FatalError("Py_Initialize: can't make first thread");
- (void) PyThreadState_Swap(tstate);
-
-#ifdef WITH_THREAD
- /* We can't call _PyEval_FiniThreads() in Py_Finalize because
- destroying the GIL might fail when it is being referenced from
- another running thread (see issue #9901).
- Instead we destroy the previously created GIL here, which ensures
- that we can call Py_Initialize / Py_Finalize multiple times. */
- _PyEval_FiniThreads();
-
- /* Auto-thread-state API */
- _PyGILState_Init(interp, tstate);
-#endif /* WITH_THREAD */
-
- _Py_ReadyTypes();
-
- if (!_PyFrame_Init())
- Py_FatalError("Py_Initialize: can't init frames");
-
- if (!_PyLong_Init())
- Py_FatalError("Py_Initialize: can't init longs");
-
- if (!PyByteArray_Init())
- Py_FatalError("Py_Initialize: can't init bytearray");
-
- if (!_PyFloat_Init())
- Py_FatalError("Py_Initialize: can't init float");
-
- interp->modules = PyDict_New();
- if (interp->modules == NULL)
- Py_FatalError("Py_Initialize: can't make modules dictionary");
-
- /* Init Unicode implementation; relies on the codec registry */
- if (_PyUnicode_Init() < 0)
- Py_FatalError("Py_Initialize: can't initialize unicode");
- if (_PyStructSequence_Init() < 0)
- Py_FatalError("Py_Initialize: can't initialize structseq");
-
- bimod = _PyBuiltin_Init();
- if (bimod == NULL)
- Py_FatalError("Py_Initialize: can't initialize builtins modules");
- _PyImport_FixupBuiltin(bimod, "builtins");
- interp->builtins = PyModule_GetDict(bimod);
- if (interp->builtins == NULL)
- Py_FatalError("Py_Initialize: can't initialize builtins dict");
- Py_INCREF(interp->builtins);
-
- /* initialize builtin exceptions */
- _PyExc_Init(bimod);
-
- sysmod = _PySys_Init();
- if (sysmod == NULL)
- Py_FatalError("Py_Initialize: can't initialize sys");
- interp->sysdict = PyModule_GetDict(sysmod);
- if (interp->sysdict == NULL)
- Py_FatalError("Py_Initialize: can't initialize sys dict");
- Py_INCREF(interp->sysdict);
- _PyImport_FixupBuiltin(sysmod, "sys");
- PySys_SetPath(Py_GetPath());
- PyDict_SetItemString(interp->sysdict, "modules",
- interp->modules);
-
- /* Set up a preliminary stderr printer until we have enough
- infrastructure for the io module in place. */
- pstderr = PyFile_NewStdPrinter(fileno(stderr));
- if (pstderr == NULL)
- Py_FatalError("Py_Initialize: can't set preliminary stderr");
- _PySys_SetObjectId(&PyId_stderr, pstderr);
- PySys_SetObject("__stderr__", pstderr);
- Py_DECREF(pstderr);
-
- _PyImport_Init();
-
- _PyImportHooks_Init();
-
- /* Initialize _warnings. */
- _PyWarnings_Init();
-
- if (!install_importlib)
- return;
-
- import_init(interp, sysmod);
-
- /* initialize the faulthandler module */
- if (_PyFaulthandler_Init())
- Py_FatalError("Py_Initialize: can't initialize faulthandler");
-
- if (_PyTime_Init() < 0)
- Py_FatalError("Py_Initialize: can't initialize time");
-
- if (initfsencoding(interp) < 0)
- Py_FatalError("Py_Initialize: unable to load the file system codec");
-
- if (install_sigs)
- initsigs(); /* Signal handling stuff, including initintr() */
-
- if (_PyTraceMalloc_Init() < 0)
- Py_FatalError("Py_Initialize: can't initialize tracemalloc");
-
- initmain(interp); /* Module __main__ */
- if (initstdio() < 0)
- Py_FatalError(
- "Py_Initialize: can't initialize sys standard streams");
-
- /* Initialize warnings. */
- if (PySys_HasWarnOptions()) {
- PyObject *warnings_module = PyImport_ImportModule("warnings");
- if (warnings_module == NULL) {
- fprintf(stderr, "'import warnings' failed; traceback:\n");
- PyErr_Print();
- }
- Py_XDECREF(warnings_module);
- }
-
- if (!Py_NoSiteFlag)
- initsite(); /* Module site */
-}
-
-void
-Py_InitializeEx(int install_sigs)
-{
- _Py_InitializeEx_Private(install_sigs, 1);
-}
-
-void
-Py_Initialize(void)
-{
- Py_InitializeEx(1);
-}
-
-
-#ifdef COUNT_ALLOCS
-extern void dump_counts(FILE*);
-#endif
-
-/* 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 void
-flush_std_files(void)
-{
- PyObject *fout = _PySys_GetObjectId(&PyId_stdout);
- PyObject *ferr = _PySys_GetObjectId(&PyId_stderr);
- PyObject *tmp;
-
- if (fout != NULL && fout != Py_None && !file_is_closed(fout)) {
- tmp = _PyObject_CallMethodId(fout, &PyId_flush, "");
- if (tmp == NULL)
- PyErr_WriteUnraisable(fout);
- else
- Py_DECREF(tmp);
- }
-
- if (ferr != NULL && ferr != Py_None && !file_is_closed(ferr)) {
- tmp = _PyObject_CallMethodId(ferr, &PyId_flush, "");
- if (tmp == NULL)
- PyErr_Clear();
- else
- Py_DECREF(tmp);
- }
-}
-
-/* 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.
-
-*/
-
-void
-Py_Finalize(void)
-{
- PyInterpreterState *interp;
- PyThreadState *tstate;
-
- if (!initialized)
- return;
-
- wait_for_thread_shutdown();
-
- /* 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
- * interpreter 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.
- */
- call_py_exitfuncs();
-
- /* Get current thread state and interpreter pointer */
- tstate = PyThreadState_GET();
- interp = tstate->interp;
-
- /* Remaining threads (e.g. daemon threads) will automatically exit
- after taking the GIL (in PyEval_RestoreThread()). */
- _Py_Finalizing = tstate;
- initialized = 0;
-
- /* Flush stdout+stderr */
- flush_std_files();
-
- /* 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_Collect();
-#ifdef COUNT_ALLOCS
- /* With COUNT_ALLOCS, it helps to run GC multiple times:
- each collection might release some types from the type
- list, so they become garbage. */
- while (PyGC_Collect() > 0)
- /* nothing */;
-#endif
- /* Destroy all modules */
- PyImport_Cleanup();
-
- /* Flush stdout+stderr (again, in case more was printed) */
- flush_std_files();
-
- /* 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_Collect();
-#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();
-
- /* Debugging stuff */
-#ifdef COUNT_ALLOCS
- dump_counts(stdout);
-#endif
- /* dump hash stats */
- _PyHash_Fini();
-
- PRINT_TOTAL_REFS();
-
-#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 (Py_GETENV("PYTHONDUMPREFS"))
- _Py_PrintReferences(stderr);
-#endif /* Py_TRACE_REFS */
-
- /* Clear interpreter state and all thread states. */
- PyInterpreterState_Clear(interp);
-
- /* Now we decref the exception classes. After this point nothing
- can raise an exception. That's okay, because each Fini() method
- below has been checked to make sure no exceptions are ever
- raised.
- */
-
- _PyExc_Fini();
-
- /* Sundry finalizers */
- PyMethod_Fini();
- PyFrame_Fini();
- PyCFunction_Fini();
- PyTuple_Fini();
- PyList_Fini();
- PySet_Fini();
- PyBytes_Fini();
- PyByteArray_Fini();
- PyLong_Fini();
- PyFloat_Fini();
- PyDict_Fini();
- PySlice_Fini();
- _PyGC_Fini();
- _PyRandom_Fini();
-
- /* Cleanup Unicode implementation */
- _PyUnicode_Fini();
-
- /* reset file system default encoding */
- if (!Py_HasFileSystemDefaultEncoding && Py_FileSystemDefaultEncoding) {
- PyMem_RawFree((char*)Py_FileSystemDefaultEncoding);
- Py_FileSystemDefaultEncoding = NULL;
- }
-
- /* XXX Still allocated:
- - various static ad-hoc pointers to interned strings
- - int and float free list blocks
- - whatever various modules and libraries allocate
- */
-
- PyGrammar_RemoveAccelerators(&_PyParser_Grammar);
-
- /* Cleanup auto-thread-state */
-#ifdef WITH_THREAD
- _PyGILState_Fini();
-#endif /* WITH_THREAD */
-
- /* Delete current thread. After this, many C API calls become crashy. */
- PyThreadState_Swap(NULL);
- PyInterpreterState_Delete(interp);
-
-#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 (Py_GETENV("PYTHONDUMPREFS"))
- _Py_PrintReferenceAddresses(stderr);
-#endif /* Py_TRACE_REFS */
-#ifdef PYMALLOC_DEBUG
- if (Py_GETENV("PYTHONMALLOCSTATS"))
- _PyObject_DebugMallocStats(stderr);
-#endif
-
- call_ll_exitfuncs();
-}
-
-/* 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.
-
-*/
-
-PyThreadState *
-Py_NewInterpreter(void)
-{
- PyInterpreterState *interp;
- PyThreadState *tstate, *save_tstate;
- PyObject *bimod, *sysmod;
-
- if (!initialized)
- Py_FatalError("Py_NewInterpreter: call Py_Initialize first");
-
- interp = PyInterpreterState_New();
- if (interp == NULL)
- return NULL;
-
- tstate = PyThreadState_New(interp);
- if (tstate == NULL) {
- PyInterpreterState_Delete(interp);
- return NULL;
- }
-
- save_tstate = PyThreadState_Swap(tstate);
-
- /* XXX The following is lax in error checking */
-
- interp->modules = PyDict_New();
-
- bimod = _PyImport_FindBuiltin("builtins");
- if (bimod != NULL) {
- interp->builtins = PyModule_GetDict(bimod);
- if (interp->builtins == NULL)
- goto handle_error;
- Py_INCREF(interp->builtins);
- }
-
- /* initialize builtin exceptions */
- _PyExc_Init(bimod);
-
- sysmod = _PyImport_FindBuiltin("sys");
- if (bimod != NULL && sysmod != NULL) {
- PyObject *pstderr;
-
- interp->sysdict = PyModule_GetDict(sysmod);
- if (interp->sysdict == NULL)
- goto handle_error;
- Py_INCREF(interp->sysdict);
- PySys_SetPath(Py_GetPath());
- PyDict_SetItemString(interp->sysdict, "modules",
- interp->modules);
- /* Set up a preliminary stderr printer until we have enough
- infrastructure for the io module in place. */
- pstderr = PyFile_NewStdPrinter(fileno(stderr));
- if (pstderr == NULL)
- Py_FatalError("Py_Initialize: can't set preliminary stderr");
- _PySys_SetObjectId(&PyId_stderr, pstderr);
- PySys_SetObject("__stderr__", pstderr);
- Py_DECREF(pstderr);
-
- _PyImportHooks_Init();
-
- import_init(interp, sysmod);
-
- if (initfsencoding(interp) < 0)
- goto handle_error;
-
- if (initstdio() < 0)
- Py_FatalError(
- "Py_Initialize: can't initialize sys standard streams");
- initmain(interp);
- if (!Py_NoSiteFlag)
- initsite();
- }
-
- if (!PyErr_Occurred())
- return tstate;
-
-handle_error:
- /* Oops, it didn't work. Undo it all. */
-
- PyErr_PrintEx(0);
- PyThreadState_Clear(tstate);
- PyThreadState_Swap(save_tstate);
- PyThreadState_Delete(tstate);
- PyInterpreterState_Delete(interp);
-
- return NULL;
-}
-
-/* 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_Finalize() 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("Py_EndInterpreter: thread is not current");
- if (tstate->frame != NULL)
- Py_FatalError("Py_EndInterpreter: thread still has a frame");
-
- wait_for_thread_shutdown();
-
- if (tstate != interp->tstate_head || tstate->next != NULL)
- Py_FatalError("Py_EndInterpreter: not the last thread");
-
- PyImport_Cleanup();
- PyInterpreterState_Clear(interp);
- PyThreadState_Swap(NULL);
- PyInterpreterState_Delete(interp);
-}
-
-#ifdef MS_WINDOWS
-static wchar_t *progname = L"python";
-#else
-static wchar_t *progname = L"python3";
-#endif
-
-void
-Py_SetProgramName(wchar_t *pn)
-{
- if (pn && *pn)
- progname = pn;
-}
-
-wchar_t *
-Py_GetProgramName(void)
-{
- return progname;
-}
-
-static wchar_t *default_home = NULL;
-static wchar_t env_home[MAXPATHLEN+1];
-
-void
-Py_SetPythonHome(wchar_t *home)
-{
- default_home = home;
-}
-
-wchar_t *
-Py_GetPythonHome(void)
-{
- wchar_t *home = default_home;
- if (home == NULL && !Py_IgnoreEnvironmentFlag) {
- char* chome = Py_GETENV("PYTHONHOME");
- if (chome) {
- size_t size = Py_ARRAY_LENGTH(env_home);
- size_t r = mbstowcs(env_home, chome, size);
- if (r != (size_t)-1 && r < size)
- home = env_home;
- }
-
- }
- return home;
-}
-
-/* Create __main__ module */
-
-static void
-initmain(PyInterpreterState *interp)
-{
- PyObject *m, *d, *loader;
- m = PyImport_AddModule("__main__");
- if (m == NULL)
- Py_FatalError("can't create __main__ module");
- d = PyModule_GetDict(m);
- if (PyDict_GetItemString(d, "__builtins__") == NULL) {
- PyObject *bimod = PyImport_ImportModule("builtins");
- if (bimod == NULL) {
- Py_FatalError("Failed to retrieve builtins module");
- }
- if (PyDict_SetItemString(d, "__builtins__", bimod) < 0) {
- Py_FatalError("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_FatalError("Failed to retrieve BuiltinImporter");
- }
- if (PyDict_SetItemString(d, "__loader__", loader) < 0) {
- Py_FatalError("Failed to initialize __main__.__loader__");
- }
- Py_DECREF(loader);
- }
-}
-
-static int
-initfsencoding(PyInterpreterState *interp)
-{
- PyObject *codec;
-
- if (Py_FileSystemDefaultEncoding == NULL)
- {
- Py_FileSystemDefaultEncoding = get_locale_encoding();
- if (Py_FileSystemDefaultEncoding == NULL)
- Py_FatalError("Py_Initialize: Unable to get the locale encoding");
-
- Py_HasFileSystemDefaultEncoding = 0;
- interp->fscodec_initialized = 1;
- return 0;
- }
-
- /* the encoding is mbcs, utf-8 or ascii */
- codec = _PyCodec_Lookup(Py_FileSystemDefaultEncoding);
- if (!codec) {
- /* Such error can only occurs in critical situations: no more
- * memory, import a module of the standard library failed,
- * etc. */
- return -1;
- }
- Py_DECREF(codec);
- interp->fscodec_initialized = 1;
- return 0;
-}
-
-/* Import the site module (not into __main__ though) */
-
-static void
-initsite(void)
-{
- PyObject *m;
- m = PyImport_ImportModule("site");
- if (m == NULL) {
- fprintf(stderr, "Failed to import the site module\n");
- PyErr_Print();
- Py_Finalize();
- exit(1);
- }
- else {
- Py_DECREF(m);
- }
-}
-
-static PyObject*
-create_stdio(PyObject* io,
- int fd, int write_mode, char* name,
- char* encoding, char* errors)
-{
- PyObject *buf = NULL, *stream = NULL, *text = NULL, *raw = NULL, *res;
- const char* mode;
- const char* newline;
- PyObject *line_buffering;
- int buffering, isatty;
- _Py_IDENTIFIER(open);
- _Py_IDENTIFIER(isatty);
- _Py_IDENTIFIER(TextIOWrapper);
- _Py_IDENTIFIER(mode);
-
- /* 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 (Py_UnbufferedStdioFlag && write_mode)
- buffering = 0;
- else
- buffering = -1;
- if (write_mode)
- mode = "wb";
- else
- mode = "rb";
- buf = _PyObject_CallMethodId(io, &PyId_open, "isiOOOi",
- fd, mode, buffering,
- Py_None, Py_None, Py_None, 0);
- 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);
- }
-
- text = PyUnicode_FromString(name);
- if (text == NULL || _PyObject_SetAttrId(raw, &PyId_name, text) < 0)
- goto error;
- res = _PyObject_CallMethodId(raw, &PyId_isatty, "");
- if (res == NULL)
- goto error;
- isatty = PyObject_IsTrue(res);
- Py_DECREF(res);
- if (isatty == -1)
- goto error;
- if (isatty || Py_UnbufferedStdioFlag)
- 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
-
- stream = _PyObject_CallMethodId(io, &PyId_TextIOWrapper, "OsssO",
- buf, encoding, errors,
- newline, line_buffering);
- Py_CLEAR(buf);
- 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);
- return NULL;
-}
-
-static int
-is_valid_fd(int fd)
-{
- int dummy_fd;
- if (fd < 0 || !_PyVerify_fd(fd))
- return 0;
- dummy_fd = dup(fd);
- if (dummy_fd < 0)
- return 0;
- close(dummy_fd);
- return 1;
-}
-
-/* Initialize sys.stdin, stdout, stderr and builtins.open */
-static int
-initstdio(void)
-{
- PyObject *iomod = NULL, *wrapper;
- PyObject *bimod = NULL;
- PyObject *m;
- PyObject *std = NULL;
- int status = 0, fd;
- PyObject * encoding_attr;
- char *pythonioencoding = NULL, *encoding, *errors;
-
- /* 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 (!(bimod = PyImport_ImportModule("builtins"))) {
- goto error;
- }
-
- if (!(iomod = PyImport_ImportModule("io"))) {
- goto error;
- }
- if (!(wrapper = PyObject_GetAttrString(iomod, "OpenWrapper"))) {
- goto error;
- }
-
- /* Set builtins.open */
- if (PyObject_SetAttrString(bimod, "open", wrapper) == -1) {
- Py_DECREF(wrapper);
- goto error;
- }
- Py_DECREF(wrapper);
-
- encoding = _Py_StandardStreamEncoding;
- errors = _Py_StandardStreamErrors;
- if (!encoding || !errors) {
- if (!errors) {
- /* When the LC_CTYPE locale is the POSIX locale ("C locale"),
- stdin and stdout use the surrogateescape error handler by
- default, instead of the strict error handler. */
- char *loc = setlocale(LC_CTYPE, NULL);
- if (loc != NULL && strcmp(loc, "C") == 0)
- errors = "surrogateescape";
- }
-
- pythonioencoding = Py_GETENV("PYTHONIOENCODING");
- if (pythonioencoding) {
- char *err;
- pythonioencoding = _PyMem_Strdup(pythonioencoding);
- if (pythonioencoding == NULL) {
- PyErr_NoMemory();
- goto error;
- }
- err = strchr(pythonioencoding, ':');
- if (err) {
- *err = '\0';
- err++;
- if (*err && !_Py_StandardStreamErrors) {
- errors = err;
- }
- }
- if (*pythonioencoding && !encoding) {
- encoding = pythonioencoding;
- }
- }
- }
-
- /* 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.
- */
- if (!is_valid_fd(fd)) {
- std = Py_None;
- Py_INCREF(std);
- }
- else {
- std = create_stdio(iomod, fd, 0, "<stdin>", encoding, errors);
- if (std == NULL)
- goto error;
- } /* if (fd < 0) */
- PySys_SetObject("__stdin__", std);
- _PySys_SetObjectId(&PyId_stdin, std);
- Py_DECREF(std);
-
- /* Set sys.stdout */
- fd = fileno(stdout);
- if (!is_valid_fd(fd)) {
- std = Py_None;
- Py_INCREF(std);
- }
- else {
- std = create_stdio(iomod, fd, 1, "<stdout>", encoding, errors);
- if (std == NULL)
- goto error;
- } /* if (fd < 0) */
- 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 (!is_valid_fd(fd)) {
- std = Py_None;
- Py_INCREF(std);
- }
- else {
- std = create_stdio(iomod, fd, 1, "<stderr>", encoding, "backslashreplace");
- if (std == NULL)
- goto error;
- } /* if (fd < 0) */
-
- /* 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;
- std_encoding = _PyUnicode_AsString(encoding_attr);
- if (std_encoding != NULL) {
- PyObject *codec_info = _PyCodec_Lookup(std_encoding);
- Py_XDECREF(codec_info);
- }
- Py_DECREF(encoding_attr);
- }
- PyErr_Clear(); /* 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
-
- if (0) {
- error:
- status = -1;
- }
-
- /* We won't need them anymore. */
- if (_Py_StandardStreamEncoding) {
- PyMem_RawFree(_Py_StandardStreamEncoding);
- _Py_StandardStreamEncoding = NULL;
- }
- if (_Py_StandardStreamErrors) {
- PyMem_RawFree(_Py_StandardStreamErrors);
- _Py_StandardStreamErrors = NULL;
- }
- PyMem_Free(pythonioencoding);
- Py_XDECREF(bimod);
- Py_XDECREF(iomod);
- return status;
-}
/* Parse input from a file and execute it */
@@ -1327,7 +110,7 @@ PyRun_InteractiveLoopFlags(FILE *fp, const char *filename_str, PyCompilerFlags *
err = -1;
for (;;) {
ret = PyRun_InteractiveOneObject(fp, filename, flags);
- PRINT_TOTAL_REFS();
+ _PY_DEBUG_PRINT_TOTAL_REFS();
if (ret == E_EOF) {
err = 0;
break;
@@ -2592,192 +1375,6 @@ cleanup:
}
}
-/* Print fatal error message and abort */
-
-void
-Py_FatalError(const char *msg)
-{
- const int fd = fileno(stderr);
- PyThreadState *tstate;
-
- fprintf(stderr, "Fatal Python error: %s\n", msg);
- fflush(stderr); /* it helps in Windows debug build */
- if (PyErr_Occurred()) {
- PyErr_PrintEx(0);
- }
- else {
- tstate = _Py_atomic_load_relaxed(&_PyThreadState_Current);
- if (tstate != NULL) {
- fputc('\n', stderr);
- fflush(stderr);
- _Py_DumpTracebackThreads(fd, tstate->interp, tstate);
- }
- _PyFaulthandler_Fini();
- }
-
-#ifdef MS_WINDOWS
- {
- size_t len = strlen(msg);
- WCHAR* buffer;
- size_t i;
-
- /* 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. */
- buffer = alloca( (len+1) * (sizeof *buffer));
- for( i=0; i<=len; ++i)
- buffer[i] = msg[i];
- OutputDebugStringW(L"Fatal Python error: ");
- OutputDebugStringW(buffer);
- OutputDebugStringW(L"\n");
- }
-#ifdef _DEBUG
- DebugBreak();
-#endif
-#endif /* MS_WINDOWS */
- abort();
-}
-
-/* Clean up and exit */
-
-#ifdef WITH_THREAD
-#include "pythread.h"
-#endif
-
-static void (*pyexitfunc)(void) = NULL;
-/* For the atexit module. */
-void _Py_PyAtExit(void (*func)(void))
-{
- pyexitfunc = func;
-}
-
-static void
-call_py_exitfuncs(void)
-{
- if (pyexitfunc == NULL)
- return;
-
- (*pyexitfunc)();
- PyErr_Clear();
-}
-
-/* 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(void)
-{
-#ifdef WITH_THREAD
- _Py_IDENTIFIER(_shutdown);
- PyObject *result;
- PyThreadState *tstate = PyThreadState_GET();
- PyObject *threading = PyMapping_GetItemString(tstate->interp->modules,
- "threading");
- if (threading == NULL) {
- /* threading not imported */
- PyErr_Clear();
- return;
- }
- result = _PyObject_CallMethodId(threading, &PyId__shutdown, "");
- if (result == NULL) {
- PyErr_WriteUnraisable(threading);
- }
- else {
- Py_DECREF(result);
- }
- Py_DECREF(threading);
-#endif
-}
-
-#define NEXITFUNCS 32
-static void (*exitfuncs[NEXITFUNCS])(void);
-static int nexitfuncs = 0;
-
-int Py_AtExit(void (*func)(void))
-{
- if (nexitfuncs >= NEXITFUNCS)
- return -1;
- exitfuncs[nexitfuncs++] = func;
- return 0;
-}
-
-static void
-call_ll_exitfuncs(void)
-{
- while (nexitfuncs > 0)
- (*exitfuncs[--nexitfuncs])();
-
- fflush(stdout);
- fflush(stderr);
-}
-
-void
-Py_Exit(int sts)
-{
- Py_Finalize();
-
- exit(sts);
-}
-
-static void
-initsigs(void)
-{
-#ifdef SIGPIPE
- PyOS_setsig(SIGPIPE, SIG_IGN);
-#endif
-#ifdef SIGXFZ
- PyOS_setsig(SIGXFZ, SIG_IGN);
-#endif
-#ifdef SIGXFSZ
- PyOS_setsig(SIGXFSZ, SIG_IGN);
-#endif
- PyOS_InitInterrupts(); /* May imply initsignal() */
- if (PyErr_Occurred()) {
- Py_FatalError("Py_Initialize: can't import signal");
- }
-}
-
-
-/* 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.
- */
-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);
-}
-
#if defined(USE_STACKCHECK)
#if defined(WIN32) && defined(_MSC_VER)
@@ -2816,73 +1413,6 @@ PyOS_CheckStack(void)
#endif /* USE_STACKCHECK */
-
-/* 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
-}
-
/* Deprecated C API functions still provided for binary compatiblity */
#undef PyParser_SimpleParseFile
diff --git a/Python/sysmodule.c b/Python/sysmodule.c
index 106fc84..6fb882f 100644
--- a/Python/sysmodule.c
+++ b/Python/sysmodule.c
@@ -1681,7 +1681,7 @@ _PySys_Init(void)
}
#endif
- /* stdin/stdout/stderr are now set by pythonrun.c */
+ /* stdin/stdout/stderr are set in pylifecycle.c */
SET_SYS_FROM_STRING_BORROW("__displayhook__",
PyDict_GetItemString(sysdict, "displayhook"));