]> granicus.if.org Git - python/commitdiff
The last of the mass checkins for separate (sub)interpreters.
authorGuido van Rossum <guido@python.org>
Sat, 2 Aug 1997 03:10:38 +0000 (03:10 +0000)
committerGuido van Rossum <guido@python.org>
Sat, 2 Aug 1997 03:10:38 +0000 (03:10 +0000)
Everything should now work again.

See the comments for the .h files mass checkin (e.g. pystate.h) for
more detail.

Python/bltinmodule.c
Python/ceval.c
Python/import.c
Python/importdl.c
Python/pystate.c
Python/pythonrun.c
Python/sysmodule.c

index 245d31ead9b62c4bfbc574f5219dbe39204a8a9c..439498dc2af833b43f99318a5f9e0bf746c2fdbb 100644 (file)
@@ -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();
 }
 
 
index 205d8d42e069e1631b325a1fc5c8d1d5e52d94a3..bb0fb65c794a9180d08dc52673cf2b968611a78b 100644 (file)
@@ -129,6 +129,18 @@ PyEval_InitThreads()
        main_thread = get_thread_ident();
 }
 
+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;
 }
index aa1272bcc89bdd6504c21b4ac0f8783256fb9798..2a77e5a3597e6cc91d8e93060aae882ab9175e0a 100644 (file)
@@ -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;
index 44f57ac358aac456279385a1a42466f71478475b..b372e46b59c8d96b996ed773f41eab3ebb0c0f5d 100644 (file)
@@ -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 */
index bf2bdf4a1f3e77cd9ed1a8d36aab816412244d4f..138dc0989d9cc0b8b31e7cd52ae33f5a89e37f2f 100644 (file)
@@ -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;
 }
index caa0a4cce5c7d21d082a2f9a7a6ecfb758c02c36..d0fe2fc8d7f80c499282ed0b332c4830536ee60f 100644 (file)
@@ -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 */
 
index da4043834952d6afe962b9589aec5d0c59fc26f6..68b176f43075e7fac94732b781907e2055b32fa8 100644 (file)
@@ -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 *