summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Python/bltinmodule.c121
-rw-r--r--Python/ceval.c29
-rw-r--r--Python/import.c166
-rw-r--r--Python/importdl.c14
-rw-r--r--Python/pystate.c128
-rw-r--r--Python/pythonrun.c252
-rw-r--r--Python/sysmodule.c50
7 files changed, 542 insertions, 218 deletions
diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c
index 245d31e..439498d 100644
--- a/Python/bltinmodule.c
+++ b/Python/bltinmodule.c
@@ -1668,21 +1668,6 @@ static PyMethodDef builtin_methods[] = {
{NULL, NULL},
};
-static PyObject *builtin_mod;
-static PyObject *builtin_dict;
-
-PyObject *
-PyBuiltin_GetModule()
-{
- return builtin_mod;
-}
-
-PyObject *
-PyBuiltin_GetDict()
-{
- return builtin_dict;
-}
-
/* Predefined exceptions */
PyObject *PyExc_AccessError;
@@ -1707,54 +1692,90 @@ PyObject *PyExc_ValueError;
PyObject *PyExc_ZeroDivisionError;
static PyObject *
-newstdexception(name)
+newstdexception(dict, name)
+ PyObject *dict;
char *name;
{
PyObject *v = PyString_FromString(name);
- if (v == NULL || PyDict_SetItemString(builtin_dict, name, v) != 0)
+ if (v == NULL || PyDict_SetItemString(dict, name, v) != 0)
Py_FatalError("no mem for new standard exception");
return v;
}
static void
-initerrors()
+initerrors(dict)
+ PyObject *dict;
{
- PyExc_AccessError = newstdexception("AccessError");
- PyExc_AssertionError = newstdexception("AssertionError");
- PyExc_AttributeError = newstdexception("AttributeError");
- PyExc_EOFError = newstdexception("EOFError");
- PyExc_FloatingPointError = newstdexception("FloatingPointError");
- PyExc_IOError = newstdexception("IOError");
- PyExc_ImportError = newstdexception("ImportError");
- PyExc_IndexError = newstdexception("IndexError");
- PyExc_KeyError = newstdexception("KeyError");
- PyExc_KeyboardInterrupt = newstdexception("KeyboardInterrupt");
- PyExc_MemoryError = newstdexception("MemoryError");
- PyExc_NameError = newstdexception("NameError");
- PyExc_OverflowError = newstdexception("OverflowError");
- PyExc_RuntimeError = newstdexception("RuntimeError");
- PyExc_SyntaxError = newstdexception("SyntaxError");
- PyExc_SystemError = newstdexception("SystemError");
- PyExc_SystemExit = newstdexception("SystemExit");
- PyExc_TypeError = newstdexception("TypeError");
- PyExc_ValueError = newstdexception("ValueError");
- PyExc_ZeroDivisionError = newstdexception("ZeroDivisionError");
+ PyExc_AccessError = newstdexception(dict, "AccessError");
+ PyExc_AssertionError = newstdexception(dict, "AssertionError");
+ PyExc_AttributeError = newstdexception(dict, "AttributeError");
+ PyExc_EOFError = newstdexception(dict, "EOFError");
+ PyExc_FloatingPointError = newstdexception(dict, "FloatingPointError");
+ PyExc_IOError = newstdexception(dict, "IOError");
+ PyExc_ImportError = newstdexception(dict, "ImportError");
+ PyExc_IndexError = newstdexception(dict, "IndexError");
+ PyExc_KeyError = newstdexception(dict, "KeyError");
+ PyExc_KeyboardInterrupt = newstdexception(dict, "KeyboardInterrupt");
+ PyExc_MemoryError = newstdexception(dict, "MemoryError");
+ PyExc_NameError = newstdexception(dict, "NameError");
+ PyExc_OverflowError = newstdexception(dict, "OverflowError");
+ PyExc_RuntimeError = newstdexception(dict, "RuntimeError");
+ PyExc_SyntaxError = newstdexception(dict, "SyntaxError");
+ PyExc_SystemError = newstdexception(dict, "SystemError");
+ PyExc_SystemExit = newstdexception(dict, "SystemExit");
+ PyExc_TypeError = newstdexception(dict, "TypeError");
+ PyExc_ValueError = newstdexception(dict, "ValueError");
+ PyExc_ZeroDivisionError = newstdexception(dict, "ZeroDivisionError");
+}
+
+static void
+finierrors()
+{
+ Py_XDECREF(PyExc_AccessError); PyExc_AccessError = NULL;
+ Py_XDECREF(PyExc_AssertionError); PyExc_AssertionError = NULL;
+ Py_XDECREF(PyExc_AttributeError); PyExc_AttributeError = NULL;
+ Py_XDECREF(PyExc_EOFError); PyExc_EOFError = NULL;
+ Py_XDECREF(PyExc_FloatingPointError); PyExc_FloatingPointError = NULL;
+ Py_XDECREF(PyExc_IOError); PyExc_IOError = NULL;
+ Py_XDECREF(PyExc_ImportError); PyExc_ImportError = NULL;
+ Py_XDECREF(PyExc_IndexError); PyExc_IndexError = NULL;
+ Py_XDECREF(PyExc_KeyError); PyExc_KeyError = NULL;
+ Py_XDECREF(PyExc_KeyboardInterrupt); PyExc_KeyboardInterrupt = NULL;
+ Py_XDECREF(PyExc_MemoryError); PyExc_MemoryError = NULL;
+ Py_XDECREF(PyExc_NameError); PyExc_NameError = NULL;
+ Py_XDECREF(PyExc_OverflowError); PyExc_OverflowError = NULL;
+ Py_XDECREF(PyExc_RuntimeError); PyExc_RuntimeError = NULL;
+ Py_XDECREF(PyExc_SyntaxError); PyExc_SyntaxError = NULL;
+ Py_XDECREF(PyExc_SystemError); PyExc_SystemError = NULL;
+ Py_XDECREF(PyExc_SystemExit); PyExc_SystemExit = NULL;
+ Py_XDECREF(PyExc_TypeError); PyExc_TypeError = NULL;
+ Py_XDECREF(PyExc_ValueError); PyExc_ValueError = NULL;
+ Py_XDECREF(PyExc_ZeroDivisionError); PyExc_ZeroDivisionError = NULL;
+}
+
+PyObject *
+_PyBuiltin_Init()
+{
+ PyObject *mod, *dict;
+ mod = Py_InitModule("__builtin__", builtin_methods);
+ if (mod == NULL)
+ return NULL;
+ dict = PyModule_GetDict(mod);
+ initerrors(dict);
+ if (PyDict_SetItemString(dict, "None", Py_None) < 0)
+ return NULL;
+ if (PyDict_SetItemString(dict, "Ellipsis", Py_Ellipsis) < 0)
+ return NULL;
+ if (PyDict_SetItemString(dict, "__debug__",
+ PyInt_FromLong(Py_OptimizeFlag == 0)) < 0)
+ return NULL;
+ return mod;
}
void
-PyBuiltin_Init()
+_PyBuiltin_Fini()
{
- builtin_mod = Py_InitModule("__builtin__", builtin_methods);
- builtin_dict = PyModule_GetDict(builtin_mod);
- Py_INCREF(builtin_dict);
- initerrors();
- (void) PyDict_SetItemString(builtin_dict, "None", Py_None);
- (void) PyDict_SetItemString(builtin_dict, "Ellipsis", Py_Ellipsis);
- (void) PyDict_SetItemString(builtin_dict, "__debug__",
- PyInt_FromLong(Py_OptimizeFlag == 0));
- if (PyErr_Occurred())
- Py_FatalError(
- "error creating None/Ellipsis/__debug__ in __builtin__");
+ finierrors();
}
diff --git a/Python/ceval.c b/Python/ceval.c
index 205d8d4..bb0fb65 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -130,6 +130,18 @@ PyEval_InitThreads()
}
void
+PyEval_AcquireLock()
+{
+ acquire_lock(interpreter_lock, 1);
+}
+
+void
+PyEval_ReleaseLock()
+{
+ release_lock(interpreter_lock);
+}
+
+void
PyEval_AcquireThread(tstate)
PyThreadState *tstate;
{
@@ -402,9 +414,6 @@ eval_code2(co, globals, locals,
/* Start of code */
- if (tstate == NULL)
- Py_FatalError("eval_code2 called without a current thread");
-
#ifdef USE_STACKCHECK
if (tstate->recursion_depth%10 == 0 && PyOS_CheckStack()) {
PyErr_SetString(PyExc_MemoryError, "Stack overflow");
@@ -590,7 +599,7 @@ eval_code2(co, globals, locals,
Py_MakePendingCalls() above. */
if (things_to_do || --tstate->ticker < 0) {
- tstate->ticker = tstate->sys_checkinterval;
+ tstate->ticker = tstate->interp->checkinterval;
if (things_to_do) {
if (Py_MakePendingCalls() < 0) {
why = WHY_EXCEPTION;
@@ -612,14 +621,15 @@ eval_code2(co, globals, locals,
if (interpreter_lock) {
/* Give another thread a chance */
- PyThreadState *tstate =
- PyThreadState_Swap(NULL);
+ if (PyThreadState_Swap(NULL) != tstate)
+ Py_FatalError("ceval: tstate mix-up");
release_lock(interpreter_lock);
/* Other threads may run now */
acquire_lock(interpreter_lock, 1);
- PyThreadState_Swap(tstate);
+ if (PyThreadState_Swap(tstate) != NULL)
+ Py_FatalError("ceval: orphan tstate");
}
#endif
}
@@ -2176,9 +2186,10 @@ call_trace(p_trace, p_newtrace, f, msg, arg)
PyObject *
PyEval_GetBuiltins()
{
- PyFrameObject *current_frame = PyThreadState_Get()->frame;
+ PyThreadState *tstate = PyThreadState_Get();
+ PyFrameObject *current_frame = tstate->frame;
if (current_frame == NULL)
- return PyBuiltin_GetModule();
+ return tstate->interp->builtins;
else
return current_frame->f_builtins;
}
diff --git a/Python/import.c b/Python/import.c
index aa1272b..2a77e5a 100644
--- a/Python/import.c
+++ b/Python/import.c
@@ -61,18 +61,15 @@ extern long PyOS_GetLastModificationTime(); /* In getmtime.c */
/* New way to come up with the magic number: (YEAR-1995), MONTH, DAY */
#define MAGIC (20121 | ((long)'\r'<<16) | ((long)'\n'<<24))
-static PyObject *_PyImport_Modules; /* This becomes sys.modules */
+/* See _PyImport_FixupExtension() below */
+static PyObject *extensions = NULL;
/* Initialize things */
void
-PyImport_Init()
+_PyImport_Init()
{
- if (_PyImport_Modules != NULL)
- Py_FatalError("duplicate initimport() call");
- if ((_PyImport_Modules = PyDict_New()) == NULL)
- Py_FatalError("no mem for dictionary of modules");
if (Py_OptimizeFlag) {
/* Replace ".pyc" with ".pyo" in import_filetab */
struct filedescr *p;
@@ -83,21 +80,44 @@ PyImport_Init()
}
}
+void
+_PyImport_Fini()
+{
+ Py_XDECREF(extensions);
+ extensions = NULL;
+}
+
+
+/* Helper for sys */
+
+PyObject *
+PyImport_GetModuleDict()
+{
+ PyInterpreterState *interp = PyThreadState_Get()->interp;
+ if (interp->modules == NULL)
+ Py_FatalError("PyImport_GetModuleDict: no module dictionary!");
+ return interp->modules;
+}
+
/* Un-initialize things, as good as we can */
void
PyImport_Cleanup()
{
- if (_PyImport_Modules != NULL) {
- PyObject *tmp = _PyImport_Modules;
- _PyImport_Modules = NULL;
- /* This deletes all modules from sys.modules.
- When a module is deallocated, it in turn clears its
- dictionary, thus hopefully breaking any circular
- references between modules and between a module's
- dictionary and its functions. Note that "import"
- will fail while we are cleaning up. */
+ PyInterpreterState *interp = PyThreadState_Get()->interp;
+ PyObject *tmp = interp->modules;
+ if (tmp != NULL) {
+ int pos;
+ PyObject *key, *value;
+ interp->modules = NULL;
+ pos = 0;
+ while (PyDict_Next(tmp, &pos, &key, &value)) {
+ if (PyModule_Check(value)) {
+ PyObject *d = PyModule_GetDict(value);
+ PyDict_Clear(d);
+ }
+ }
PyDict_Clear(tmp);
Py_DECREF(tmp);
}
@@ -113,12 +133,70 @@ PyImport_GetMagicNumber()
}
-/* Helper for sysmodule.c -- return modules dictionary */
+/* Magic for extension modules (built-in as well as dynamically
+ loaded). To prevent initializing an extension module more than
+ once, we keep a static dictionary 'extensions' keyed by module name
+ (for built-in modules) or by filename (for dynamically loaded
+ modules), containing these modules. A copy od the module's
+ dictionary is stored by calling _PyImport_FixupExtension()
+ immediately after the module initialization function succeeds. A
+ copy can be retrieved from there by calling
+ _PyImport_FindExtension(). */
PyObject *
-PyImport_GetModuleDict()
+_PyImport_FixupExtension(name, filename)
+ char *name;
+ char *filename;
+{
+ PyObject *modules, *mod, *dict, *copy;
+ if (extensions == NULL) {
+ extensions = PyDict_New();
+ if (extensions == NULL)
+ return NULL;
+ }
+ modules = PyImport_GetModuleDict();
+ mod = PyDict_GetItemString(modules, name);
+ if (mod == NULL || !PyModule_Check(mod)) {
+ PyErr_SetString(PyExc_SystemError,
+ "_PyImport_FixupExtension: module not loaded");
+ return NULL;
+ }
+ dict = PyModule_GetDict(mod);
+ if (dict == NULL)
+ return NULL;
+ copy = PyObject_CallMethod(dict, "copy", "");
+ if (copy == NULL)
+ return NULL;
+ PyDict_SetItemString(extensions, filename, copy);
+ Py_DECREF(copy);
+ return copy;
+}
+
+PyObject *
+_PyImport_FindExtension(name, filename)
+ char *name;
+ char *filename;
{
- return _PyImport_Modules;
+ PyObject *dict, *mod, *mdict, *result;
+ if (extensions == NULL)
+ return NULL;
+ dict = PyDict_GetItemString(extensions, filename);
+ if (dict == NULL)
+ return NULL;
+ mod = PyImport_AddModule(name);
+ if (mod == NULL)
+ return NULL;
+ mdict = PyModule_GetDict(mod);
+ if (mdict == NULL)
+ return NULL;
+ result = PyObject_CallMethod(mdict, "update", "O", dict);
+ if (result == NULL)
+ return NULL;
+ Py_DECREF(result);
+ if (Py_VerboseFlag)
+ fprintf(stderr, "import %s # previously loaded (%s)\n",
+ name, filename);
+ return mod;
}
@@ -132,20 +210,16 @@ PyObject *
PyImport_AddModule(name)
char *name;
{
+ PyObject *modules = PyImport_GetModuleDict();
PyObject *m;
- if (_PyImport_Modules == NULL) {
- PyErr_SetString(PyExc_SystemError,
- "sys.modules has been deleted");
- return NULL;
- }
- if ((m = PyDict_GetItemString(_PyImport_Modules, name)) != NULL &&
+ if ((m = PyDict_GetItemString(modules, name)) != NULL &&
PyModule_Check(m))
return m;
m = PyModule_New(name);
if (m == NULL)
return NULL;
- if (PyDict_SetItemString(_PyImport_Modules, name, m) != 0) {
+ if (PyDict_SetItemString(modules, name, m) != 0) {
Py_DECREF(m);
return NULL;
}
@@ -163,6 +237,7 @@ PyImport_ExecCodeModule(name, co)
char *name;
PyObject *co;
{
+ PyObject *modules = PyImport_GetModuleDict();
PyObject *m, *d, *v;
m = PyImport_AddModule(name);
@@ -183,7 +258,7 @@ PyImport_ExecCodeModule(name, co)
return NULL;
Py_DECREF(v);
- if ((m = PyDict_GetItemString(_PyImport_Modules, name)) == NULL) {
+ if ((m = PyDict_GetItemString(modules, name)) == NULL) {
PyErr_SetString(PyExc_SystemError,
"loaded module not found in sys.modules");
return NULL;
@@ -573,20 +648,27 @@ static int
init_builtin(name)
char *name;
{
- int i;
- for (i = 0; _PyImport_Inittab[i].name != NULL; i++) {
- if (strcmp(name, _PyImport_Inittab[i].name) == 0) {
- if (_PyImport_Inittab[i].initfunc == NULL) {
+ PyInterpreterState *interp = PyThreadState_Get()->interp;
+ struct _inittab *p;
+ PyObject *mod;
+
+ if ((mod = _PyImport_FindExtension(name, name)) != NULL)
+ return 1;
+
+ for (p = _PyImport_Inittab; p->name != NULL; p++) {
+ if (strcmp(name, p->name) == 0) {
+ if (p->initfunc == NULL) {
PyErr_SetString(PyExc_ImportError,
"Cannot re-init internal module");
return -1;
}
if (Py_VerboseFlag)
- fprintf(stderr, "import %s # builtin\n",
- name);
- (*_PyImport_Inittab[i].initfunc)();
+ fprintf(stderr, "import %s # builtin\n", name);
+ (*p->initfunc)();
if (PyErr_Occurred())
return -1;
+ if (_PyImport_FixupExtension(name, name) == NULL)
+ return -1;
return 1;
}
}
@@ -666,14 +748,10 @@ PyObject *
PyImport_ImportModule(name)
char *name;
{
+ PyObject *modules = PyImport_GetModuleDict();
PyObject *m;
- if (_PyImport_Modules == NULL) {
- PyErr_SetString(PyExc_SystemError,
- "sys.modules has been deleted");
- return NULL;
- }
- if ((m = PyDict_GetItemString(_PyImport_Modules, name)) != NULL) {
+ if ((m = PyDict_GetItemString(modules, name)) != NULL) {
Py_INCREF(m);
}
else {
@@ -682,7 +760,7 @@ PyImport_ImportModule(name)
(i = PyImport_ImportFrozenModule(name))) {
if (i < 0)
return NULL;
- if ((m = PyDict_GetItemString(_PyImport_Modules,
+ if ((m = PyDict_GetItemString(modules,
name)) == NULL) {
if (PyErr_Occurred() == NULL)
PyErr_SetString(PyExc_SystemError,
@@ -706,6 +784,7 @@ PyObject *
PyImport_ReloadModule(m)
PyObject *m;
{
+ PyObject *modules = PyImport_GetModuleDict();
char *name;
int i;
@@ -717,12 +796,7 @@ PyImport_ReloadModule(m)
name = PyModule_GetName(m);
if (name == NULL)
return NULL;
- if (_PyImport_Modules == NULL) {
- PyErr_SetString(PyExc_SystemError,
- "sys.modules has been deleted");
- return NULL;
- }
- if (m != PyDict_GetItemString(_PyImport_Modules, name)) {
+ if (m != PyDict_GetItemString(modules, name)) {
PyErr_SetString(PyExc_ImportError,
"reload() module not in sys.modules");
return NULL;
diff --git a/Python/importdl.c b/Python/importdl.c
index 44f57ac..b372e46 100644
--- a/Python/importdl.c
+++ b/Python/importdl.c
@@ -246,6 +246,10 @@ _PyImport_LoadDynamicModule(name, pathname, fp)
pathname = pathbuf;
}
#endif
+ if ((m = _PyImport_FindExtension(name, pathname)) != NULL) {
+ Py_INCREF(m);
+ return m;
+ }
sprintf(funcname, FUNCNAME_PATTERN, name);
#ifdef USE_SHLIB
if (fp != NULL) {
@@ -518,13 +522,15 @@ _PyImport_LoadDynamicModule(name, pathname, fp)
return NULL;
}
(*p)();
- /* XXX Need check for err_occurred() here */
+ if (PyErr_Occurred())
+ return NULL;
+ if (_PyImport_FixupExtension(name, pathname) == NULL)
+ return NULL;
m = PyDict_GetItemString(PyImport_GetModuleDict(), name);
if (m == NULL) {
- if (PyErr_Occurred() == NULL)
- PyErr_SetString(PyExc_SystemError,
- "dynamic module not initialized properly");
+ PyErr_SetString(PyExc_SystemError,
+ "dynamic module not initialized properly");
return NULL;
}
/* Remember the filename as the __file__ attribute */
diff --git a/Python/pystate.c b/Python/pystate.c
index bf2bdf4..138dc09 100644
--- a/Python/pystate.c
+++ b/Python/pystate.c
@@ -33,6 +33,14 @@ PERFORMANCE OF THIS SOFTWARE.
#include "Python.h"
+#define ZAP(x) { \
+ PyObject *tmp = (PyObject *)(x); \
+ (x) = NULL; \
+ Py_XDECREF(tmp); \
+}
+
+
+static PyInterpreterState *interp_head = NULL;
static PyThreadState *current_tstate = NULL;
@@ -41,23 +49,65 @@ PyInterpreterState *
PyInterpreterState_New()
{
PyInterpreterState *interp = PyMem_NEW(PyInterpreterState, 1);
+
if (interp != NULL) {
- interp->import_modules = NULL;
+ interp->modules = NULL;
interp->sysdict = NULL;
- interp->nthreads = 0;
- interp->nexitfuncs = 0;
+ interp->builtins = NULL;
+ interp->checkinterval = 10;
+ interp->tstate_head = NULL;
+
+ interp->next = interp_head;
+ interp_head = interp;
}
+
return interp;
}
void
-PyInterpreterState_Delete(interp)
+PyInterpreterState_Clear(interp)
+ PyInterpreterState *interp;
+{
+ PyThreadState *p;
+ for (p = interp->tstate_head; p != NULL; p = p->next)
+ PyThreadState_Clear(p);
+ ZAP(interp->modules);
+ ZAP(interp->sysdict);
+ ZAP(interp->builtins);
+}
+
+
+static void
+zapthreads(interp)
PyInterpreterState *interp;
{
- Py_XDECREF(interp->import_modules);
- Py_XDECREF(interp->sysdict);
+ PyThreadState *p, *q;
+ p = interp->tstate_head;
+ while (p != NULL) {
+ q = p->next;
+ PyThreadState_Delete(p);
+ p = q;
+ }
+}
+
+void
+PyInterpreterState_Delete(interp)
+ PyInterpreterState *interp;
+{
+ PyInterpreterState **p;
+ zapthreads(interp);
+ for (p = &interp_head; ; p = &(*p)->next) {
+ if (*p == NULL)
+ Py_FatalError(
+ "PyInterpreterState_Delete: invalid interp");
+ if (*p == interp)
+ break;
+ }
+ if (interp->tstate_head != NULL)
+ Py_FatalError("PyInterpreterState_Delete: remaining threads");
+ *p = interp->next;
PyMem_DEL(interp);
}
@@ -67,9 +117,9 @@ PyThreadState_New(interp)
PyInterpreterState *interp;
{
PyThreadState *tstate = PyMem_NEW(PyThreadState, 1);
- /* fprintf(stderr, "new tstate -> %p\n", tstate); */
+
if (tstate != NULL) {
- tstate->interpreter_state = interp;
+ tstate->interp = interp;
tstate->frame = NULL;
tstate->recursion_depth = 0;
@@ -86,36 +136,59 @@ PyThreadState_New(interp)
tstate->sys_profilefunc = NULL;
tstate->sys_tracefunc = NULL;
- tstate->sys_checkinterval = 0;
- interp->nthreads++;
+ tstate->next = interp->tstate_head;
+ interp->tstate_head = tstate;
}
+
return tstate;
}
void
-PyThreadState_Delete(tstate)
+PyThreadState_Clear(tstate)
PyThreadState *tstate;
{
- /* fprintf(stderr, "delete tstate %p\n", tstate); */
- if (tstate == current_tstate)
- current_tstate = NULL;
- tstate->interpreter_state->nthreads--;
+ if (tstate->frame != NULL)
+ fprintf(stderr,
+ "PyThreadState_Clear: warning: thread still has a frame");
+
+ ZAP(tstate->frame);
- Py_XDECREF((PyObject *) (tstate->frame)); /* XXX really? */
+ ZAP(tstate->curexc_type);
+ ZAP(tstate->curexc_value);
+ ZAP(tstate->curexc_traceback);
- Py_XDECREF(tstate->curexc_type);
- Py_XDECREF(tstate->curexc_value);
- Py_XDECREF(tstate->curexc_traceback);
+ ZAP(tstate->exc_type);
+ ZAP(tstate->exc_value);
+ ZAP(tstate->exc_traceback);
- Py_XDECREF(tstate->exc_type);
- Py_XDECREF(tstate->exc_value);
- Py_XDECREF(tstate->exc_traceback);
+ ZAP(tstate->sys_profilefunc);
+ ZAP(tstate->sys_tracefunc);
+}
- Py_XDECREF(tstate->sys_profilefunc);
- Py_XDECREF(tstate->sys_tracefunc);
+void
+PyThreadState_Delete(tstate)
+ PyThreadState *tstate;
+{
+ PyInterpreterState *interp;
+ PyThreadState **p;
+ if (tstate == NULL)
+ Py_FatalError("PyThreadState_Delete: NULL tstate");
+ if (tstate == current_tstate)
+ Py_FatalError("PyThreadState_Delete: tstate is still current");
+ interp = tstate->interp;
+ if (interp == NULL)
+ Py_FatalError("PyThreadState_Delete: NULL interp");
+ for (p = &interp->tstate_head; ; p = &(*p)->next) {
+ if (*p == NULL)
+ Py_FatalError(
+ "PyThreadState_Delete: invalid tstate");
+ if (*p == tstate)
+ break;
+ }
+ *p = tstate->next;
PyMem_DEL(tstate);
}
@@ -123,7 +196,9 @@ PyThreadState_Delete(tstate)
PyThreadState *
PyThreadState_Get()
{
- /* fprintf(stderr, "get tstate -> %p\n", current_tstate); */
+ if (current_tstate == NULL)
+ Py_FatalError("PyThreadState_Get: no current thread");
+
return current_tstate;
}
@@ -133,7 +208,8 @@ PyThreadState_Swap(new)
PyThreadState *new;
{
PyThreadState *old = current_tstate;
- /* fprintf(stderr, "swap tstate new=%p <--> old=%p\n", new, old); */
+
current_tstate = new;
+
return old;
}
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 */
diff --git a/Python/sysmodule.c b/Python/sysmodule.c
index da40438..68b176f 100644
--- a/Python/sysmodule.c
+++ b/Python/sysmodule.c
@@ -52,8 +52,6 @@ Data members:
#include <unistd.h>
#endif
-static PyObject *sysdict;
-
#ifdef MS_COREDLL
extern void *PyWin_DLLhModule;
#endif
@@ -62,7 +60,9 @@ PyObject *
PySys_GetObject(name)
char *name;
{
- return PyDict_GetItemString(sysdict, name);
+ PyThreadState *tstate = PyThreadState_Get();
+ PyObject *sd = tstate->interp->sysdict;
+ return PyDict_GetItemString(sd, name);
}
FILE *
@@ -84,14 +84,16 @@ PySys_SetObject(name, v)
char *name;
PyObject *v;
{
+ PyThreadState *tstate = PyThreadState_Get();
+ PyObject *sd = tstate->interp->sysdict;
if (v == NULL) {
- if (PyDict_GetItemString(sysdict, name) == NULL)
+ if (PyDict_GetItemString(sd, name) == NULL)
return 0;
else
- return PyDict_DelItemString(sysdict, name);
+ return PyDict_DelItemString(sd, name);
}
else
- return PyDict_SetItemString(sysdict, name, v);
+ return PyDict_SetItemString(sd, name, v);
}
static PyObject *
@@ -103,8 +105,6 @@ sys_exc_info(self, args)
if (!PyArg_Parse(args, ""))
return NULL;
tstate = PyThreadState_Get();
- if (tstate == NULL)
- Py_FatalError("sys.exc_info(): no thread state");
return Py_BuildValue(
"(OOO)",
tstate->exc_type != NULL ? tstate->exc_type : Py_None,
@@ -161,7 +161,7 @@ sys_setcheckinterval(self, args)
PyObject *args;
{
PyThreadState *tstate = PyThreadState_Get();
- if (!PyArg_ParseTuple(args, "i", &tstate->sys_checkinterval))
+ if (!PyArg_ParseTuple(args, "i", &tstate->interp->checkinterval))
return NULL;
Py_INCREF(Py_None);
return Py_None;
@@ -242,8 +242,6 @@ static PyMethodDef sys_methods[] = {
{NULL, NULL} /* sentinel */
};
-static PyObject *sysin, *sysout, *syserr;
-
static PyObject *
list_builtin_module_names()
{
@@ -271,24 +269,28 @@ list_builtin_module_names()
return list;
}
-void
-PySys_Init()
+PyObject *
+_PySys_Init()
{
extern int fclose Py_PROTO((FILE *));
- PyObject *m = Py_InitModule("sys", sys_methods);
- PyObject *v;
+ PyThreadState *tstate;
+ PyObject *m, *v, *sysdict;
+ PyObject *sysin, *sysout, *syserr;
+
+ m = Py_InitModule("sys", sys_methods);
sysdict = PyModule_GetDict(m);
- Py_INCREF(sysdict);
- /* NB keep an extra ref to the std files to avoid closing them
- when the user deletes them */
- sysin = PyFile_FromFile(stdin, "<stdin>", "r", fclose);
- sysout = PyFile_FromFile(stdout, "<stdout>", "w", fclose);
- syserr = PyFile_FromFile(stderr, "<stderr>", "w", fclose);
+
+ sysin = PyFile_FromFile(stdin, "<stdin>", "r", NULL);
+ sysout = PyFile_FromFile(stdout, "<stdout>", "w", NULL);
+ syserr = PyFile_FromFile(stderr, "<stderr>", "w", NULL);
if (PyErr_Occurred())
- Py_FatalError("can't initialize sys.std{in,out,err}");
+ return NULL;
PyDict_SetItemString(sysdict, "stdin", sysin);
PyDict_SetItemString(sysdict, "stdout", sysout);
PyDict_SetItemString(sysdict, "stderr", syserr);
+ Py_XDECREF(sysin);
+ Py_XDECREF(sysout);
+ Py_XDECREF(syserr);
PyDict_SetItemString(sysdict, "version",
v = PyString_FromString(Py_GetVersion()));
Py_XDECREF(v);
@@ -310,7 +312,6 @@ PySys_Init()
PyDict_SetItemString(sysdict, "maxint",
v = PyInt_FromLong(PyInt_GetMax()));
Py_XDECREF(v);
- PyDict_SetItemString(sysdict, "modules", PyImport_GetModuleDict());
PyDict_SetItemString(sysdict, "builtin_module_names",
v = list_builtin_module_names());
Py_XDECREF(v);
@@ -323,7 +324,8 @@ PySys_Init()
Py_XDECREF(v);
#endif
if (PyErr_Occurred())
- Py_FatalError("can't insert sys.* objects in sys dict");
+ return NULL;
+ return m;
}
static PyObject *