summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTim Peters <tim.peters@gmail.com>2000-09-02 09:16:15 (GMT)
committerTim Peters <tim.peters@gmail.com>2000-09-02 09:16:15 (GMT)
commit412f2460248b21e8d09a57afe98cdb33c16025bc (patch)
tree0e52674cb9a87ed87bb9f519bec68e428219b119
parentf2b332dc7e94f5df1965913c6be443980e8727fe (diff)
downloadcpython-412f2460248b21e8d09a57afe98cdb33c16025bc.zip
cpython-412f2460248b21e8d09a57afe98cdb33c16025bc.tar.gz
cpython-412f2460248b21e8d09a57afe98cdb33c16025bc.tar.bz2
PyInterpreterState_New is not thread-safe, and the recent fix to _PyPclose
can cause it to get called by multiple threads simultaneously. Ditto for PyInterpreterState_Delete. Of the former, the docs say "The interpreter lock need not be held, but may be held if it is necessary to serialize calls to this function". This kinda implies it both is and isn't thread-safe. Of the latter, the docs merely say "The interpreter lock need not be held.", and the clause about serializing is absent. I expect it was *believed* these are both thread-safe, and the bit about serializing via the global lock was meant as a permission rather than a caution. I also expect we've never seen a problem here because the Python core (prior to the _PyPclose fix) only calls these functions once per run. The Py_NewInterpreter subsystem exposed by the C API (but not used by Python itself) also calls them, but that subsystem appears to be very rarely used. Whatever, they're both thread-safe now.
-rw-r--r--Python/pystate.c4
1 files changed, 4 insertions, 0 deletions
diff --git a/Python/pystate.c b/Python/pystate.c
index 85a9ce7..0651ab0 100644
--- a/Python/pystate.c
+++ b/Python/pystate.c
@@ -40,8 +40,10 @@ PyInterpreterState_New(void)
interp->checkinterval = 10;
interp->tstate_head = NULL;
+ HEAD_LOCK();
interp->next = interp_head;
interp_head = interp;
+ HEAD_UNLOCK();
}
return interp;
@@ -79,6 +81,7 @@ PyInterpreterState_Delete(PyInterpreterState *interp)
{
PyInterpreterState **p;
zapthreads(interp);
+ HEAD_LOCK();
for (p = &interp_head; ; p = &(*p)->next) {
if (*p == NULL)
Py_FatalError(
@@ -89,6 +92,7 @@ PyInterpreterState_Delete(PyInterpreterState *interp)
if (interp->tstate_head != NULL)
Py_FatalError("PyInterpreterState_Delete: remaining threads");
*p = interp->next;
+ HEAD_UNLOCK();
PyMem_DEL(interp);
}