Commit 170497e4 authored by Guido van Rossum's avatar Guido van Rossum

The last of the mass checkins for separate (sub)interpreters.

Everything should now work again.

See the comments for the .h files mass checkin (e.g. pystate.h) for
more detail.
parent e781f9bc
...@@ -1668,21 +1668,6 @@ static PyMethodDef builtin_methods[] = { ...@@ -1668,21 +1668,6 @@ static PyMethodDef builtin_methods[] = {
{NULL, NULL}, {NULL, NULL},
}; };
static PyObject *builtin_mod;
static PyObject *builtin_dict;
PyObject *
PyBuiltin_GetModule()
{
return builtin_mod;
}
PyObject *
PyBuiltin_GetDict()
{
return builtin_dict;
}
/* Predefined exceptions */ /* Predefined exceptions */
PyObject *PyExc_AccessError; PyObject *PyExc_AccessError;
...@@ -1707,54 +1692,90 @@ PyObject *PyExc_ValueError; ...@@ -1707,54 +1692,90 @@ PyObject *PyExc_ValueError;
PyObject *PyExc_ZeroDivisionError; PyObject *PyExc_ZeroDivisionError;
static PyObject * static PyObject *
newstdexception(name) newstdexception(dict, name)
PyObject *dict;
char *name; char *name;
{ {
PyObject *v = PyString_FromString(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"); Py_FatalError("no mem for new standard exception");
return v; return v;
} }
static void static void
initerrors() initerrors(dict)
PyObject *dict;
{ {
PyExc_AccessError = newstdexception("AccessError"); PyExc_AccessError = newstdexception(dict, "AccessError");
PyExc_AssertionError = newstdexception("AssertionError"); PyExc_AssertionError = newstdexception(dict, "AssertionError");
PyExc_AttributeError = newstdexception("AttributeError"); PyExc_AttributeError = newstdexception(dict, "AttributeError");
PyExc_EOFError = newstdexception("EOFError"); PyExc_EOFError = newstdexception(dict, "EOFError");
PyExc_FloatingPointError = newstdexception("FloatingPointError"); PyExc_FloatingPointError = newstdexception(dict, "FloatingPointError");
PyExc_IOError = newstdexception("IOError"); PyExc_IOError = newstdexception(dict, "IOError");
PyExc_ImportError = newstdexception("ImportError"); PyExc_ImportError = newstdexception(dict, "ImportError");
PyExc_IndexError = newstdexception("IndexError"); PyExc_IndexError = newstdexception(dict, "IndexError");
PyExc_KeyError = newstdexception("KeyError"); PyExc_KeyError = newstdexception(dict, "KeyError");
PyExc_KeyboardInterrupt = newstdexception("KeyboardInterrupt"); PyExc_KeyboardInterrupt = newstdexception(dict, "KeyboardInterrupt");
PyExc_MemoryError = newstdexception("MemoryError"); PyExc_MemoryError = newstdexception(dict, "MemoryError");
PyExc_NameError = newstdexception("NameError"); PyExc_NameError = newstdexception(dict, "NameError");
PyExc_OverflowError = newstdexception("OverflowError"); PyExc_OverflowError = newstdexception(dict, "OverflowError");
PyExc_RuntimeError = newstdexception("RuntimeError"); PyExc_RuntimeError = newstdexception(dict, "RuntimeError");
PyExc_SyntaxError = newstdexception("SyntaxError"); PyExc_SyntaxError = newstdexception(dict, "SyntaxError");
PyExc_SystemError = newstdexception("SystemError"); PyExc_SystemError = newstdexception(dict, "SystemError");
PyExc_SystemExit = newstdexception("SystemExit"); PyExc_SystemExit = newstdexception(dict, "SystemExit");
PyExc_TypeError = newstdexception("TypeError"); PyExc_TypeError = newstdexception(dict, "TypeError");
PyExc_ValueError = newstdexception("ValueError"); PyExc_ValueError = newstdexception(dict, "ValueError");
PyExc_ZeroDivisionError = newstdexception("ZeroDivisionError"); 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 void
PyBuiltin_Init() _PyBuiltin_Fini()
{ {
builtin_mod = Py_InitModule("__builtin__", builtin_methods); finierrors();
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__");
} }
......
...@@ -129,6 +129,18 @@ PyEval_InitThreads() ...@@ -129,6 +129,18 @@ PyEval_InitThreads()
main_thread = get_thread_ident(); main_thread = get_thread_ident();
} }
void
PyEval_AcquireLock()
{
acquire_lock(interpreter_lock, 1);
}
void
PyEval_ReleaseLock()
{
release_lock(interpreter_lock);
}
void void
PyEval_AcquireThread(tstate) PyEval_AcquireThread(tstate)
PyThreadState *tstate; PyThreadState *tstate;
...@@ -402,9 +414,6 @@ eval_code2(co, globals, locals, ...@@ -402,9 +414,6 @@ eval_code2(co, globals, locals,
/* Start of code */ /* Start of code */
if (tstate == NULL)
Py_FatalError("eval_code2 called without a current thread");
#ifdef USE_STACKCHECK #ifdef USE_STACKCHECK
if (tstate->recursion_depth%10 == 0 && PyOS_CheckStack()) { if (tstate->recursion_depth%10 == 0 && PyOS_CheckStack()) {
PyErr_SetString(PyExc_MemoryError, "Stack overflow"); PyErr_SetString(PyExc_MemoryError, "Stack overflow");
...@@ -590,7 +599,7 @@ eval_code2(co, globals, locals, ...@@ -590,7 +599,7 @@ eval_code2(co, globals, locals,
Py_MakePendingCalls() above. */ Py_MakePendingCalls() above. */
if (things_to_do || --tstate->ticker < 0) { if (things_to_do || --tstate->ticker < 0) {
tstate->ticker = tstate->sys_checkinterval; tstate->ticker = tstate->interp->checkinterval;
if (things_to_do) { if (things_to_do) {
if (Py_MakePendingCalls() < 0) { if (Py_MakePendingCalls() < 0) {
why = WHY_EXCEPTION; why = WHY_EXCEPTION;
...@@ -612,14 +621,15 @@ eval_code2(co, globals, locals, ...@@ -612,14 +621,15 @@ eval_code2(co, globals, locals,
if (interpreter_lock) { if (interpreter_lock) {
/* Give another thread a chance */ /* Give another thread a chance */
PyThreadState *tstate = if (PyThreadState_Swap(NULL) != tstate)
PyThreadState_Swap(NULL); Py_FatalError("ceval: tstate mix-up");
release_lock(interpreter_lock); release_lock(interpreter_lock);
/* Other threads may run now */ /* Other threads may run now */
acquire_lock(interpreter_lock, 1); acquire_lock(interpreter_lock, 1);
PyThreadState_Swap(tstate); if (PyThreadState_Swap(tstate) != NULL)
Py_FatalError("ceval: orphan tstate");
} }
#endif #endif
} }
...@@ -2176,9 +2186,10 @@ call_trace(p_trace, p_newtrace, f, msg, arg) ...@@ -2176,9 +2186,10 @@ call_trace(p_trace, p_newtrace, f, msg, arg)
PyObject * PyObject *
PyEval_GetBuiltins() PyEval_GetBuiltins()
{ {
PyFrameObject *current_frame = PyThreadState_Get()->frame; PyThreadState *tstate = PyThreadState_Get();
PyFrameObject *current_frame = tstate->frame;
if (current_frame == NULL) if (current_frame == NULL)
return PyBuiltin_GetModule(); return tstate->interp->builtins;
else else
return current_frame->f_builtins; return current_frame->f_builtins;
} }
......
...@@ -61,18 +61,15 @@ extern long PyOS_GetLastModificationTime(); /* In getmtime.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 */ /* New way to come up with the magic number: (YEAR-1995), MONTH, DAY */
#define MAGIC (20121 | ((long)'\r'<<16) | ((long)'\n'<<24)) #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 */ /* Initialize things */
void 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) { if (Py_OptimizeFlag) {
/* Replace ".pyc" with ".pyo" in import_filetab */ /* Replace ".pyc" with ".pyo" in import_filetab */
struct filedescr *p; struct filedescr *p;
...@@ -83,21 +80,44 @@ PyImport_Init() ...@@ -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 */ /* Un-initialize things, as good as we can */
void void
PyImport_Cleanup() PyImport_Cleanup()
{ {
if (_PyImport_Modules != NULL) { PyInterpreterState *interp = PyThreadState_Get()->interp;
PyObject *tmp = _PyImport_Modules; PyObject *tmp = interp->modules;
_PyImport_Modules = NULL; if (tmp != NULL) {
/* This deletes all modules from sys.modules. int pos;
When a module is deallocated, it in turn clears its PyObject *key, *value;
dictionary, thus hopefully breaking any circular interp->modules = NULL;
references between modules and between a module's pos = 0;
dictionary and its functions. Note that "import" while (PyDict_Next(tmp, &pos, &key, &value)) {
will fail while we are cleaning up. */ if (PyModule_Check(value)) {
PyObject *d = PyModule_GetDict(value);
PyDict_Clear(d);
}
}
PyDict_Clear(tmp); PyDict_Clear(tmp);
Py_DECREF(tmp); Py_DECREF(tmp);
} }
...@@ -113,12 +133,70 @@ PyImport_GetMagicNumber() ...@@ -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 * PyObject *
PyImport_GetModuleDict() _PyImport_FixupExtension(name, filename)
char *name;
char *filename;
{ {
return _PyImport_Modules; 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;
{
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 * ...@@ -132,20 +210,16 @@ PyObject *
PyImport_AddModule(name) PyImport_AddModule(name)
char *name; char *name;
{ {
PyObject *modules = PyImport_GetModuleDict();
PyObject *m; PyObject *m;
if (_PyImport_Modules == NULL) { if ((m = PyDict_GetItemString(modules, name)) != NULL &&
PyErr_SetString(PyExc_SystemError,
"sys.modules has been deleted");
return NULL;
}
if ((m = PyDict_GetItemString(_PyImport_Modules, name)) != NULL &&
PyModule_Check(m)) PyModule_Check(m))
return m; return m;
m = PyModule_New(name); m = PyModule_New(name);
if (m == NULL) if (m == NULL)
return NULL; return NULL;
if (PyDict_SetItemString(_PyImport_Modules, name, m) != 0) { if (PyDict_SetItemString(modules, name, m) != 0) {
Py_DECREF(m); Py_DECREF(m);
return NULL; return NULL;
} }
...@@ -163,6 +237,7 @@ PyImport_ExecCodeModule(name, co) ...@@ -163,6 +237,7 @@ PyImport_ExecCodeModule(name, co)
char *name; char *name;
PyObject *co; PyObject *co;
{ {
PyObject *modules = PyImport_GetModuleDict();
PyObject *m, *d, *v; PyObject *m, *d, *v;
m = PyImport_AddModule(name); m = PyImport_AddModule(name);
...@@ -183,7 +258,7 @@ PyImport_ExecCodeModule(name, co) ...@@ -183,7 +258,7 @@ PyImport_ExecCodeModule(name, co)
return NULL; return NULL;
Py_DECREF(v); Py_DECREF(v);
if ((m = PyDict_GetItemString(_PyImport_Modules, name)) == NULL) { if ((m = PyDict_GetItemString(modules, name)) == NULL) {
PyErr_SetString(PyExc_SystemError, PyErr_SetString(PyExc_SystemError,
"loaded module not found in sys.modules"); "loaded module not found in sys.modules");
return NULL; return NULL;
...@@ -573,20 +648,27 @@ static int ...@@ -573,20 +648,27 @@ static int
init_builtin(name) init_builtin(name)
char *name; char *name;
{ {
int i; PyInterpreterState *interp = PyThreadState_Get()->interp;
for (i = 0; _PyImport_Inittab[i].name != NULL; i++) { struct _inittab *p;
if (strcmp(name, _PyImport_Inittab[i].name) == 0) { PyObject *mod;
if (_PyImport_Inittab[i].initfunc == NULL) {
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, PyErr_SetString(PyExc_ImportError,
"Cannot re-init internal module"); "Cannot re-init internal module");
return -1; return -1;
} }
if (Py_VerboseFlag) if (Py_VerboseFlag)
fprintf(stderr, "import %s # builtin\n", fprintf(stderr, "import %s # builtin\n", name);
name); (*p->initfunc)();
(*_PyImport_Inittab[i].initfunc)();
if (PyErr_Occurred()) if (PyErr_Occurred())
return -1; return -1;
if (_PyImport_FixupExtension(name, name) == NULL)
return -1;
return 1; return 1;
} }
} }
...@@ -666,14 +748,10 @@ PyObject * ...@@ -666,14 +748,10 @@ PyObject *
PyImport_ImportModule(name) PyImport_ImportModule(name)
char *name; char *name;
{ {
PyObject *modules = PyImport_GetModuleDict();
PyObject *m; PyObject *m;
if (_PyImport_Modules == NULL) { if ((m = PyDict_GetItemString(modules, name)) != NULL) {
PyErr_SetString(PyExc_SystemError,
"sys.modules has been deleted");
return NULL;
}
if ((m = PyDict_GetItemString(_PyImport_Modules, name)) != NULL) {
Py_INCREF(m); Py_INCREF(m);
} }
else { else {
...@@ -682,7 +760,7 @@ PyImport_ImportModule(name) ...@@ -682,7 +760,7 @@ PyImport_ImportModule(name)
(i = PyImport_ImportFrozenModule(name))) { (i = PyImport_ImportFrozenModule(name))) {
if (i < 0) if (i < 0)
return NULL; return NULL;
if ((m = PyDict_GetItemString(_PyImport_Modules, if ((m = PyDict_GetItemString(modules,
name)) == NULL) { name)) == NULL) {
if (PyErr_Occurred() == NULL) if (PyErr_Occurred() == NULL)
PyErr_SetString(PyExc_SystemError, PyErr_SetString(PyExc_SystemError,
...@@ -706,6 +784,7 @@ PyObject * ...@@ -706,6 +784,7 @@ PyObject *
PyImport_ReloadModule(m) PyImport_ReloadModule(m)
PyObject *m; PyObject *m;
{ {
PyObject *modules = PyImport_GetModuleDict();
char *name; char *name;
int i; int i;
...@@ -717,12 +796,7 @@ PyImport_ReloadModule(m) ...@@ -717,12 +796,7 @@ PyImport_ReloadModule(m)
name = PyModule_GetName(m); name = PyModule_GetName(m);
if (name == NULL) if (name == NULL)
return NULL; return NULL;
if (_PyImport_Modules == NULL) { if (m != PyDict_GetItemString(modules, name)) {
PyErr_SetString(PyExc_SystemError,
"sys.modules has been deleted");
return NULL;
}
if (m != PyDict_GetItemString(_PyImport_Modules, name)) {
PyErr_SetString(PyExc_ImportError, PyErr_SetString(PyExc_ImportError,
"reload() module not in sys.modules"); "reload() module not in sys.modules");
return NULL; return NULL;
......
...@@ -246,6 +246,10 @@ _PyImport_LoadDynamicModule(name, pathname, fp) ...@@ -246,6 +246,10 @@ _PyImport_LoadDynamicModule(name, pathname, fp)
pathname = pathbuf; pathname = pathbuf;
} }
#endif #endif
if ((m = _PyImport_FindExtension(name, pathname)) != NULL) {
Py_INCREF(m);
return m;
}
sprintf(funcname, FUNCNAME_PATTERN, name); sprintf(funcname, FUNCNAME_PATTERN, name);
#ifdef USE_SHLIB #ifdef USE_SHLIB
if (fp != NULL) { if (fp != NULL) {
...@@ -518,11 +522,13 @@ _PyImport_LoadDynamicModule(name, pathname, fp) ...@@ -518,11 +522,13 @@ _PyImport_LoadDynamicModule(name, pathname, fp)
return NULL; return NULL;
} }
(*p)(); (*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); m = PyDict_GetItemString(PyImport_GetModuleDict(), name);
if (m == NULL) { if (m == NULL) {
if (PyErr_Occurred() == NULL)
PyErr_SetString(PyExc_SystemError, PyErr_SetString(PyExc_SystemError,
"dynamic module not initialized properly"); "dynamic module not initialized properly");
return NULL; return NULL;
......
...@@ -33,6 +33,14 @@ PERFORMANCE OF THIS SOFTWARE. ...@@ -33,6 +33,14 @@ PERFORMANCE OF THIS SOFTWARE.
#include "Python.h" #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; static PyThreadState *current_tstate = NULL;
...@@ -41,23 +49,65 @@ PyInterpreterState * ...@@ -41,23 +49,65 @@ PyInterpreterState *
PyInterpreterState_New() PyInterpreterState_New()
{ {
PyInterpreterState *interp = PyMem_NEW(PyInterpreterState, 1); PyInterpreterState *interp = PyMem_NEW(PyInterpreterState, 1);
if (interp != NULL) { if (interp != NULL) {
interp->import_modules = NULL; interp->modules = NULL;
interp->sysdict = NULL; interp->sysdict = NULL;
interp->nthreads = 0; interp->builtins = NULL;
interp->nexitfuncs = 0; interp->checkinterval = 10;
interp->tstate_head = NULL;
interp->next = interp_head;
interp_head = interp;
} }
return interp; return interp;
} }
void 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; PyInterpreterState *interp;
{ {
Py_XDECREF(interp->import_modules); PyThreadState *p, *q;
Py_XDECREF(interp->sysdict); 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); PyMem_DEL(interp);
} }
...@@ -67,9 +117,9 @@ PyThreadState_New(interp) ...@@ -67,9 +117,9 @@ PyThreadState_New(interp)
PyInterpreterState *interp; PyInterpreterState *interp;
{ {
PyThreadState *tstate = PyMem_NEW(PyThreadState, 1); PyThreadState *tstate = PyMem_NEW(PyThreadState, 1);
/* fprintf(stderr, "new tstate -> %p\n", tstate); */
if (tstate != NULL) { if (tstate != NULL) {
tstate->interpreter_state = interp; tstate->interp = interp;
tstate->frame = NULL; tstate->frame = NULL;
tstate->recursion_depth = 0; tstate->recursion_depth = 0;
...@@ -86,36 +136,59 @@ PyThreadState_New(interp) ...@@ -86,36 +136,59 @@ PyThreadState_New(interp)
tstate->sys_profilefunc = NULL; tstate->sys_profilefunc = NULL;
tstate->sys_tracefunc = NULL; tstate->sys_tracefunc = NULL;
tstate->sys_checkinterval = 0;
interp->nthreads++; tstate->next = interp->tstate_head;
interp->tstate_head = tstate;
} }
return tstate; return tstate;
} }
void void
PyThreadState_Delete(tstate) PyThreadState_Clear(tstate)
PyThreadState *tstate; PyThreadState *tstate;
{ {
/* fprintf(stderr, "delete tstate %p\n", tstate); */ if (tstate->frame != NULL)
if (tstate == current_tstate) fprintf(stderr,
current_tstate = NULL; "PyThreadState_Clear: warning: thread still has a frame");
tstate->interpreter_state->nthreads--;
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); ZAP(tstate->exc_type);
Py_XDECREF(tstate->curexc_value); ZAP(tstate->exc_value);
Py_XDECREF(tstate->curexc_traceback); ZAP(tstate->exc_traceback);
Py_XDECREF(tstate->exc_type); ZAP(tstate->sys_profilefunc);
Py_XDECREF(tstate->exc_value); ZAP(tstate->sys_tracefunc);
Py_XDECREF(tstate->exc_traceback); }
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); PyMem_DEL(tstate);
} }
...@@ -123,7 +196,9 @@ PyThreadState_Delete(tstate) ...@@ -123,7 +196,9 @@ PyThreadState_Delete(tstate)
PyThreadState * PyThreadState *
PyThreadState_Get() PyThreadState_Get()
{ {
/* fprintf(stderr, "get tstate -> %p\n", current_tstate); */ if (current_tstate == NULL)
Py_FatalError("PyThreadState_Get: no current thread");
return current_tstate; return current_tstate;
} }
...@@ -133,7 +208,8 @@ PyThreadState_Swap(new) ...@@ -133,7 +208,8 @@ PyThreadState_Swap(new)
PyThreadState *new; PyThreadState *new;
{ {
PyThreadState *old = current_tstate; PyThreadState *old = current_tstate;
/* fprintf(stderr, "swap tstate new=%p <--> old=%p\n", new, old); */
current_tstate = new; current_tstate = new;
return old; return old;
} }
...@@ -36,7 +36,6 @@ PERFORMANCE OF THIS SOFTWARE. ...@@ -36,7 +36,6 @@ PERFORMANCE OF THIS SOFTWARE.
#include "grammar.h" #include "grammar.h"
#include "node.h" #include "node.h"
#include "parsetok.h" #include "parsetok.h"
#undef argument /* Avoid conflict on Mac */
#include "errcode.h" #include "errcode.h"
#include "compile.h" #include "compile.h"
#include "eval.h" #include "eval.h"
...@@ -52,7 +51,6 @@ PERFORMANCE OF THIS SOFTWARE. ...@@ -52,7 +51,6 @@ PERFORMANCE OF THIS SOFTWARE.
#ifdef MS_WIN32 #ifdef MS_WIN32
#undef BYTE #undef BYTE
#undef arglist
#include "windows.h" #include "windows.h"
#endif #endif
...@@ -70,65 +68,217 @@ static PyObject *run_pyc_file Py_PROTO((FILE *fp, char *filename, ...@@ -70,65 +68,217 @@ static PyObject *run_pyc_file Py_PROTO((FILE *fp, char *filename,
PyObject *globals, PyObject *locals)); PyObject *globals, PyObject *locals));
static void err_input Py_PROTO((perrdetail *)); static void err_input Py_PROTO((perrdetail *));
static void initsigs Py_PROTO((void)); static void initsigs Py_PROTO((void));
static void finisigs Py_PROTO((void));
int Py_DebugFlag; /* Needed by parser.c */ int Py_DebugFlag; /* Needed by parser.c */
int Py_VerboseFlag; /* Needed by import.c */ int Py_VerboseFlag; /* Needed by import.c */
int Py_InteractiveFlag; /* Needed by Py_FdIsInteractive() below */ 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 void
Py_Setup() Py_Initialize()
{ {
PyImport_Init(); PyInterpreterState *interp;
PyThreadState *tstate;
PyObject *bimod, *sysmod;
char *p;
/* Modules '__builtin__' and 'sys' are initialized here, if (initialized)
they are needed by random bits of the interpreter. Py_FatalError("Py_Initialize: already initialized");
All other modules are optional and are initialized initialized = 1;
when they are first imported. */
PyBuiltin_Init(); /* Also initializes builtin exceptions */ if ((p = getenv("PYTHONDEBUG")) && *p != '\0')
PySys_Init(); 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()); PySys_SetPath(Py_GetPath());
PyDict_SetItemString(interp->sysdict, "modules",
interp->modules);
_PyImport_Init();
initsigs(); /* Signal handling stuff, including initintr() */ initsigs(); /* Signal handling stuff, including initintr() */
initmain(); initmain(); /* Module __main__ */
} }
/* Create and interpreter and thread state and initialize them; /* Undo the effect of Py_Initialize().
if we already have an interpreter and thread, do nothing.
Fatal error if the creation fails. */ 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 void
Py_Initialize() Py_Finalize()
{ {
PyThreadState *tstate;
PyInterpreterState *interp; PyInterpreterState *interp;
char *p; PyThreadState *tstate;
if (PyThreadState_Get()) if (!initialized)
return; Py_FatalError("Py_Finalize: not initialized");
initialized = 0;
if ((p = getenv("PYTHONDEBUG")) && *p != '\0') tstate = PyThreadState_Get();
Py_DebugFlag = 1; interp = tstate->interp;
if ((p = getenv("PYTHONVERBOSE")) && *p != '\0')
Py_VerboseFlag = 1; 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;
PyThreadState *tstate, *save_tstate;
PyObject *bimod, *sysmod;
if (!initialized)
Py_FatalError("Py_NewInterpreter: call Py_Initialize first");
interp = PyInterpreterState_New(); interp = PyInterpreterState_New();
if (interp == NULL) if (interp == NULL)
Py_FatalError("PyInterpreterState_New() failed"); return NULL;
tstate = PyThreadState_New(interp); tstate = PyThreadState_New(interp);
if (tstate == NULL) if (tstate == NULL) {
Py_FatalError("PyThreadState_New() failed"); PyInterpreterState_Delete(interp);
(void) PyThreadState_Swap(tstate); return NULL;
}
save_tstate = PyThreadState_Swap(tstate);
/* XXX The following is lax in error checking */
Py_Setup(); 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()); PySys_SetPath(Py_GetPath());
/* XXX Who should set the path -- Setup or Initialize? */ 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"; static char *progname = "python";
...@@ -700,8 +850,13 @@ Py_Cleanup() ...@@ -700,8 +850,13 @@ Py_Cleanup()
Py_FlushLine(); Py_FlushLine();
Py_Finalize();
while (nexitfuncs > 0) while (nexitfuncs > 0)
(*exitfuncs[--nexitfuncs])(); (*exitfuncs[--nexitfuncs])();
fflush(stdout);
fflush(stderr);
} }
#ifdef COUNT_ALLOCS #ifdef COUNT_ALLOCS
...@@ -718,31 +873,6 @@ Py_Exit(sts) ...@@ -718,31 +873,6 @@ Py_Exit(sts)
dump_counts(); dump_counts();
#endif #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 #ifdef Py_REF_DEBUG
fprintf(stderr, "[%ld refs]\n", _Py_RefTotal); fprintf(stderr, "[%ld refs]\n", _Py_RefTotal);
#endif #endif
...@@ -758,8 +888,6 @@ Py_Exit(sts) ...@@ -758,8 +888,6 @@ Py_Exit(sts)
#else #else
exit(sts); exit(sts);
#endif #endif
#endif /* WITH_THREAD */
/*NOTREACHED*/
} }
#ifdef HAVE_SIGNAL_H #ifdef HAVE_SIGNAL_H
...@@ -804,6 +932,12 @@ initsigs() ...@@ -804,6 +932,12 @@ initsigs()
PyOS_InitInterrupts(); /* May imply initsignal() */ PyOS_InitInterrupts(); /* May imply initsignal() */
} }
static void
finisigs()
{
PyOS_FiniInterrupts(); /* May imply finisignal() */
}
#ifdef Py_TRACE_REFS #ifdef Py_TRACE_REFS
/* Ask a yes/no question */ /* Ask a yes/no question */
......
...@@ -52,8 +52,6 @@ Data members: ...@@ -52,8 +52,6 @@ Data members:
#include <unistd.h> #include <unistd.h>
#endif #endif
static PyObject *sysdict;
#ifdef MS_COREDLL #ifdef MS_COREDLL
extern void *PyWin_DLLhModule; extern void *PyWin_DLLhModule;
#endif #endif
...@@ -62,7 +60,9 @@ PyObject * ...@@ -62,7 +60,9 @@ PyObject *
PySys_GetObject(name) PySys_GetObject(name)
char *name; char *name;
{ {
return PyDict_GetItemString(sysdict, name); PyThreadState *tstate = PyThreadState_Get();
PyObject *sd = tstate->interp->sysdict;
return PyDict_GetItemString(sd, name);
} }
FILE * FILE *
...@@ -84,14 +84,16 @@ PySys_SetObject(name, v) ...@@ -84,14 +84,16 @@ PySys_SetObject(name, v)
char *name; char *name;
PyObject *v; PyObject *v;
{ {
PyThreadState *tstate = PyThreadState_Get();
PyObject *sd = tstate->interp->sysdict;
if (v == NULL) { if (v == NULL) {
if (PyDict_GetItemString(sysdict, name) == NULL) if (PyDict_GetItemString(sd, name) == NULL)
return 0; return 0;
else else
return PyDict_DelItemString(sysdict, name); return PyDict_DelItemString(sd, name);
} }
else else
return PyDict_SetItemString(sysdict, name, v); return PyDict_SetItemString(sd, name, v);
} }
static PyObject * static PyObject *
...@@ -103,8 +105,6 @@ sys_exc_info(self, args) ...@@ -103,8 +105,6 @@ sys_exc_info(self, args)
if (!PyArg_Parse(args, "")) if (!PyArg_Parse(args, ""))
return NULL; return NULL;
tstate = PyThreadState_Get(); tstate = PyThreadState_Get();
if (tstate == NULL)
Py_FatalError("sys.exc_info(): no thread state");
return Py_BuildValue( return Py_BuildValue(
"(OOO)", "(OOO)",
tstate->exc_type != NULL ? tstate->exc_type : Py_None, tstate->exc_type != NULL ? tstate->exc_type : Py_None,
...@@ -161,7 +161,7 @@ sys_setcheckinterval(self, args) ...@@ -161,7 +161,7 @@ sys_setcheckinterval(self, args)
PyObject *args; PyObject *args;
{ {
PyThreadState *tstate = PyThreadState_Get(); PyThreadState *tstate = PyThreadState_Get();
if (!PyArg_ParseTuple(args, "i", &tstate->sys_checkinterval)) if (!PyArg_ParseTuple(args, "i", &tstate->interp->checkinterval))
return NULL; return NULL;
Py_INCREF(Py_None); Py_INCREF(Py_None);
return Py_None; return Py_None;
...@@ -242,8 +242,6 @@ static PyMethodDef sys_methods[] = { ...@@ -242,8 +242,6 @@ static PyMethodDef sys_methods[] = {
{NULL, NULL} /* sentinel */ {NULL, NULL} /* sentinel */
}; };
static PyObject *sysin, *sysout, *syserr;
static PyObject * static PyObject *
list_builtin_module_names() list_builtin_module_names()
{ {
...@@ -271,24 +269,28 @@ list_builtin_module_names() ...@@ -271,24 +269,28 @@ list_builtin_module_names()
return list; return list;
} }
void PyObject *
PySys_Init() _PySys_Init()
{ {
extern int fclose Py_PROTO((FILE *)); extern int fclose Py_PROTO((FILE *));
PyObject *m = Py_InitModule("sys", sys_methods); PyThreadState *tstate;
PyObject *v; PyObject *m, *v, *sysdict;
PyObject *sysin, *sysout, *syserr;
m = Py_InitModule("sys", sys_methods);
sysdict = PyModule_GetDict(m); sysdict = PyModule_GetDict(m);
Py_INCREF(sysdict);
/* NB keep an extra ref to the std files to avoid closing them sysin = PyFile_FromFile(stdin, "<stdin>", "r", NULL);
when the user deletes them */ sysout = PyFile_FromFile(stdout, "<stdout>", "w", NULL);
sysin = PyFile_FromFile(stdin, "<stdin>", "r", fclose); syserr = PyFile_FromFile(stderr, "<stderr>", "w", NULL);
sysout = PyFile_FromFile(stdout, "<stdout>", "w", fclose);
syserr = PyFile_FromFile(stderr, "<stderr>", "w", fclose);
if (PyErr_Occurred()) if (PyErr_Occurred())
Py_FatalError("can't initialize sys.std{in,out,err}"); return NULL;
PyDict_SetItemString(sysdict, "stdin", sysin); PyDict_SetItemString(sysdict, "stdin", sysin);
PyDict_SetItemString(sysdict, "stdout", sysout); PyDict_SetItemString(sysdict, "stdout", sysout);
PyDict_SetItemString(sysdict, "stderr", syserr); PyDict_SetItemString(sysdict, "stderr", syserr);
Py_XDECREF(sysin);
Py_XDECREF(sysout);
Py_XDECREF(syserr);
PyDict_SetItemString(sysdict, "version", PyDict_SetItemString(sysdict, "version",
v = PyString_FromString(Py_GetVersion())); v = PyString_FromString(Py_GetVersion()));
Py_XDECREF(v); Py_XDECREF(v);
...@@ -310,7 +312,6 @@ PySys_Init() ...@@ -310,7 +312,6 @@ PySys_Init()
PyDict_SetItemString(sysdict, "maxint", PyDict_SetItemString(sysdict, "maxint",
v = PyInt_FromLong(PyInt_GetMax())); v = PyInt_FromLong(PyInt_GetMax()));
Py_XDECREF(v); Py_XDECREF(v);
PyDict_SetItemString(sysdict, "modules", PyImport_GetModuleDict());
PyDict_SetItemString(sysdict, "builtin_module_names", PyDict_SetItemString(sysdict, "builtin_module_names",
v = list_builtin_module_names()); v = list_builtin_module_names());
Py_XDECREF(v); Py_XDECREF(v);
...@@ -323,7 +324,8 @@ PySys_Init() ...@@ -323,7 +324,8 @@ PySys_Init()
Py_XDECREF(v); Py_XDECREF(v);
#endif #endif
if (PyErr_Occurred()) if (PyErr_Occurred())
Py_FatalError("can't insert sys.* objects in sys dict"); return NULL;
return m;
} }
static PyObject * static PyObject *
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment