diff options
author | Michael W. Hudson <mwh@python.net> | 2005-06-20 16:52:57 (GMT) |
---|---|---|
committer | Michael W. Hudson <mwh@python.net> | 2005-06-20 16:52:57 (GMT) |
commit | 188d4366bed88bbca777c05e7f1a5cb3878ff335 (patch) | |
tree | b77be5cef3108cf44dbf6bcd8e53dc23a77112e7 /Python | |
parent | fb662972e001aa051e5085862cf5eac323e1756f (diff) | |
download | cpython-188d4366bed88bbca777c05e7f1a5cb3878ff335.zip cpython-188d4366bed88bbca777c05e7f1a5cb3878ff335.tar.gz cpython-188d4366bed88bbca777c05e7f1a5cb3878ff335.tar.bz2 |
Fix bug:
[ 1163563 ] Sub threads execute in restricted mode
basically by fixing bug 1010677 in a non-broken way.
Backport candidate.
Diffstat (limited to 'Python')
-rw-r--r-- | Python/pystate.c | 68 |
1 files changed, 53 insertions, 15 deletions
diff --git a/Python/pystate.c b/Python/pystate.c index e2cf7c5..3ac799c 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -36,6 +36,12 @@ static PyThread_type_lock head_mutex = NULL; /* Protects interp->tstate_head */ #define HEAD_INIT() (void)(head_mutex || (head_mutex = PyThread_allocate_lock())) #define HEAD_LOCK() PyThread_acquire_lock(head_mutex, WAIT_LOCK) #define HEAD_UNLOCK() PyThread_release_lock(head_mutex) + +/* The single PyInterpreterState used by this process' + GILState implementation +*/ +static PyInterpreterState *autoInterpreterState = NULL; +static int autoTLSkey = 0; #else #define HEAD_INIT() /* Nothing */ #define HEAD_LOCK() /* Nothing */ @@ -47,6 +53,8 @@ static PyInterpreterState *interp_head = NULL; PyThreadState *_PyThreadState_Current = NULL; PyThreadFrameGetter _PyThreadState_GetFrame = NULL; +static void _PyGILState_NoteThreadState(PyThreadState* tstate); + PyInterpreterState * PyInterpreterState_New(void) @@ -180,6 +188,8 @@ PyThreadState_New(PyInterpreterState *interp) tstate->c_profileobj = NULL; tstate->c_traceobj = NULL; + _PyGILState_NoteThreadState(tstate); + HEAD_LOCK(); tstate->next = interp->tstate_head; interp->tstate_head = tstate; @@ -261,6 +271,8 @@ PyThreadState_DeleteCurrent() "PyThreadState_DeleteCurrent: no current tstate"); _PyThreadState_Current = NULL; tstate_delete_common(tstate); + if (autoTLSkey && PyThread_get_key_value(autoTLSkey) == tstate) + PyThread_delete_key_value(autoTLSkey); PyEval_ReleaseLock(); } #endif /* WITH_THREAD */ @@ -393,12 +405,6 @@ PyThreadState_IsCurrent(PyThreadState *tstate) return tstate == _PyThreadState_Current; } -/* The single PyInterpreterState used by this process' - GILState implementation -*/ -static PyInterpreterState *autoInterpreterState = NULL; -static int autoTLSkey = 0; - /* Internal initialization/finalization functions called by Py_Initialize/Py_Finalize */ @@ -408,12 +414,10 @@ _PyGILState_Init(PyInterpreterState *i, PyThreadState *t) assert(i && t); /* must init with valid states */ autoTLSkey = PyThread_create_key(); autoInterpreterState = i; - /* Now stash the thread state for this thread in TLS */ assert(PyThread_get_key_value(autoTLSkey) == NULL); - if (PyThread_set_key_value(autoTLSkey, (void *)t) < 0) - Py_FatalError("Couldn't create autoTLSkey mapping"); - assert(t->gilstate_counter == 0); /* must be a new thread state */ - t->gilstate_counter = 1; + assert(t->gilstate_counter == 0); + + _PyGILState_NoteThreadState(t); } void @@ -424,6 +428,41 @@ _PyGILState_Fini(void) autoInterpreterState = NULL;; } +/* When a thread state is created for a thread by some mechanism other than + PyGILState_Ensure, it's important that the GILState machinery knows about + it so it doesn't try to create another thread state for the thread (this is + a better fix for SF bug #1010677 than the first one attempted). +*/ +void +_PyGILState_NoteThreadState(PyThreadState* tstate) +{ + /* If autoTLSkey is 0, this must be the very first threadstate created + in Py_Initialize(). Don't do anything for now (we'll be back here + when _PyGILState_Init is called). */ + if (!autoTLSkey) + return; + + /* Stick the thread state for this thread in thread local storage. + + The only situation where you can legitimately have more than one + thread state for an OS level thread is when there are multiple + interpreters, when: + + a) You shouldn't really be using the PyGILState_ APIs anyway, + and: + + b) The slightly odd way PyThread_set_key_value works (see + comments by its implementation) means that the first thread + state created for that given OS level thread will "win", + which seems reasonable behaviour. + */ + if (PyThread_set_key_value(autoTLSkey, (void *)tstate) < 0) + Py_FatalError("Couldn't create autoTLSkey mapping"); + + /* PyGILState_Release must not try to delete this thread state. */ + tstate->gilstate_counter = 1; +} + /* The public functions */ PyThreadState * PyGILState_GetThisThreadState(void) @@ -450,8 +489,9 @@ PyGILState_Ensure(void) tcur = PyThreadState_New(autoInterpreterState); if (tcur == NULL) Py_FatalError("Couldn't create thread-state for new thread"); - if (PyThread_set_key_value(autoTLSkey, (void *)tcur) < 0) - Py_FatalError("Couldn't create autoTLSkey mapping"); + /* This is our thread state! We'll need to delete it in the + matching call to PyGILState_Release(). */ + tcur->gilstate_counter = 0; current = 0; /* new thread state is never current */ } else @@ -498,8 +538,6 @@ PyGILState_Release(PyGILState_STATE oldstate) * habit of coming back). */ PyThreadState_DeleteCurrent(); - /* Delete this thread from our TLS. */ - PyThread_delete_key_value(autoTLSkey); } /* Release the lock if necessary */ else if (oldstate == PyGILState_UNLOCKED) |