summaryrefslogtreecommitdiffstats
path: root/Python/pythonrun.c
diff options
context:
space:
mode:
Diffstat (limited to 'Python/pythonrun.c')
-rw-r--r--Python/pythonrun.c252
1 files changed, 193 insertions, 59 deletions
diff --git a/Python/pythonrun.c b/Python/pythonrun.c
index caa0a4c..d0fe2fc 100644
--- a/Python/pythonrun.c
+++ b/Python/pythonrun.c
@@ -36,7 +36,6 @@ PERFORMANCE OF THIS SOFTWARE.
#include "grammar.h"
#include "node.h"
#include "parsetok.h"
-#undef argument /* Avoid conflict on Mac */
#include "errcode.h"
#include "compile.h"
#include "eval.h"
@@ -52,7 +51,6 @@ PERFORMANCE OF THIS SOFTWARE.
#ifdef MS_WIN32
#undef BYTE
-#undef arglist
#include "windows.h"
#endif
@@ -70,65 +68,217 @@ static PyObject *run_pyc_file Py_PROTO((FILE *fp, char *filename,
PyObject *globals, PyObject *locals));
static void err_input Py_PROTO((perrdetail *));
static void initsigs Py_PROTO((void));
+static void finisigs Py_PROTO((void));
int Py_DebugFlag; /* Needed by parser.c */
int Py_VerboseFlag; /* Needed by import.c */
int Py_InteractiveFlag; /* Needed by Py_FdIsInteractive() below */
-/* Initialize the current interpreter; pass in the Python path. */
+static int initialized = 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.)
+
+*/
void
-Py_Setup()
+Py_Initialize()
{
- PyImport_Init();
-
- /* Modules '__builtin__' and 'sys' are initialized here,
- they are needed by random bits of the interpreter.
- All other modules are optional and are initialized
- when they are first imported. */
+ PyInterpreterState *interp;
+ PyThreadState *tstate;
+ PyObject *bimod, *sysmod;
+ char *p;
+
+ if (initialized)
+ Py_FatalError("Py_Initialize: already initialized");
+ initialized = 1;
- PyBuiltin_Init(); /* Also initializes builtin exceptions */
- PySys_Init();
+ if ((p = getenv("PYTHONDEBUG")) && *p != '\0')
+ Py_DebugFlag = 1;
+ if ((p = getenv("PYTHONVERBOSE")) && *p != '\0')
+ Py_VerboseFlag = 1;
+
+ 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);
+ interp->modules = PyDict_New();
+ if (interp->modules == NULL)
+ Py_FatalError("Py_Initialize: can't make modules dictionary");
+
+ bimod = _PyBuiltin_Init();
+ if (bimod == NULL)
+ Py_FatalError("Py_Initialize: can't initialize __builtin__");
+ interp->builtins = PyModule_GetDict(bimod);
+ Py_INCREF(interp->builtins);
+ _PyImport_FixupExtension("__builtin__", "__builtin__");
+
+ sysmod = _PySys_Init();
+ if (sysmod == NULL)
+ Py_FatalError("Py_Initialize: can't initialize sys");
+ interp->sysdict = PyModule_GetDict(sysmod);
+ Py_INCREF(interp->sysdict);
+ _PyImport_FixupExtension("sys", "sys");
PySys_SetPath(Py_GetPath());
+ PyDict_SetItemString(interp->sysdict, "modules",
+ interp->modules);
+
+ _PyImport_Init();
initsigs(); /* Signal handling stuff, including initintr() */
- initmain();
+ initmain(); /* Module __main__ */
}
-/* Create and interpreter and thread state and initialize them;
- if we already have an interpreter and thread, do nothing.
- Fatal error if the creation fails. */
+/* 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_Initialize()
+Py_Finalize()
{
+ PyInterpreterState *interp;
PyThreadState *tstate;
+
+ if (!initialized)
+ Py_FatalError("Py_Finalize: not initialized");
+ initialized = 0;
+
+ tstate = PyThreadState_Get();
+ interp = tstate->interp;
+
+ PyImport_Cleanup();
+ PyInterpreterState_Clear(interp);
+ PyThreadState_Swap(NULL);
+ PyInterpreterState_Delete(interp);
+
+ finisigs();
+ _PyImport_Fini();
+ _PyBuiltin_Fini();
+ PyString_Fini();
+
+ PyGrammar_RemoveAccelerators(&_PyParser_Grammar);
+}
+
+/* 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()
+{
PyInterpreterState *interp;
- char *p;
-
- if (PyThreadState_Get())
- return;
+ PyThreadState *tstate, *save_tstate;
+ PyObject *bimod, *sysmod;
- if ((p = getenv("PYTHONDEBUG")) && *p != '\0')
- Py_DebugFlag = 1;
- if ((p = getenv("PYTHONVERBOSE")) && *p != '\0')
- Py_VerboseFlag = 1;
+ if (!initialized)
+ Py_FatalError("Py_NewInterpreter: call Py_Initialize first");
interp = PyInterpreterState_New();
if (interp == NULL)
- Py_FatalError("PyInterpreterState_New() failed");
+ return NULL;
tstate = PyThreadState_New(interp);
- if (tstate == NULL)
- Py_FatalError("PyThreadState_New() failed");
- (void) PyThreadState_Swap(tstate);
+ if (tstate == NULL) {
+ PyInterpreterState_Delete(interp);
+ return NULL;
+ }
- Py_Setup();
+ save_tstate = PyThreadState_Swap(tstate);
- PySys_SetPath(Py_GetPath());
- /* XXX Who should set the path -- Setup or Initialize? */
+ /* XXX The following is lax in error checking */
+
+ interp->modules = PyDict_New();
+
+ bimod = _PyImport_FindExtension("__builtin__", "__builtin__");
+ if (bimod != NULL) {
+ interp->builtins = PyModule_GetDict(bimod);
+ Py_INCREF(interp->builtins);
+ }
+ sysmod = _PyImport_FindExtension("sys", "sys");
+ if (bimod != NULL && sysmod != NULL) {
+ interp->sysdict = PyModule_GetDict(sysmod);
+ Py_INCREF(interp->sysdict);
+ PySys_SetPath(Py_GetPath());
+ PyDict_SetItemString(interp->sysdict, "modules",
+ interp->modules);
+ initmain();
+ }
+
+ if (!PyErr_Occurred())
+ return tstate;
+
+ /* Oops, it didn't work. Undo it all. */
+
+ PyErr_Print();
+ 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(tstate)
+ 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");
+ 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);
}
static char *progname = "python";
@@ -700,8 +850,13 @@ Py_Cleanup()
Py_FlushLine();
+ Py_Finalize();
+
while (nexitfuncs > 0)
(*exitfuncs[--nexitfuncs])();
+
+ fflush(stdout);
+ fflush(stderr);
}
#ifdef COUNT_ALLOCS
@@ -718,31 +873,6 @@ Py_Exit(sts)
dump_counts();
#endif
-#ifdef WITH_THREAD
-
- /* Other threads may still be active, so skip most of the
- cleanup actions usually done (these are mostly for
- debugging anyway). */
-
- (void) PyEval_SaveThread();
-#ifndef NO_EXIT_PROG
- if (_PyThread_Started)
- _exit_prog(sts);
- else
- exit_prog(sts);
-#else /* !NO_EXIT_PROG */
- if (_PyThread_Started)
- _exit(sts);
- else
- exit(sts);
-#endif /* !NO_EXIT_PROG */
-
-#else /* WITH_THREAD */
-
- PyImport_Cleanup();
-
- PyErr_Clear();
-
#ifdef Py_REF_DEBUG
fprintf(stderr, "[%ld refs]\n", _Py_RefTotal);
#endif
@@ -758,8 +888,6 @@ Py_Exit(sts)
#else
exit(sts);
#endif
-#endif /* WITH_THREAD */
- /*NOTREACHED*/
}
#ifdef HAVE_SIGNAL_H
@@ -804,6 +932,12 @@ initsigs()
PyOS_InitInterrupts(); /* May imply initsignal() */
}
+static void
+finisigs()
+{
+ PyOS_FiniInterrupts(); /* May imply finisignal() */
+}
+
#ifdef Py_TRACE_REFS
/* Ask a yes/no question */