mirror of
https://github.com/python/cpython.git
synced 2025-09-14 20:56:06 +00:00
Fix bug:
[ 1163563 ] Sub threads execute in restricted mode basically by fixing bug 1010677 in a non-broken way. Backport candidate.
This commit is contained in:
parent
fb662972e0
commit
188d4366be
3 changed files with 65 additions and 18 deletions
|
@ -12,6 +12,12 @@ What's New in Python 2.5 alpha 1?
|
||||||
Core and builtins
|
Core and builtins
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
|
- SF bug #1163563: the original fix for bug #1010677 ("thread Module
|
||||||
|
Breaks PyGILState_Ensure()") broke badly in the case of multiple
|
||||||
|
interpreter states; back out that fix and do a better job (see
|
||||||
|
http://mail.python.org/pipermail/python-dev/2005-June/054258.html
|
||||||
|
for a longer write-up of the problem).
|
||||||
|
|
||||||
- SF patch #1180995: marshal now uses a binary format by default when
|
- SF patch #1180995: marshal now uses a binary format by default when
|
||||||
serializing floats.
|
serializing floats.
|
||||||
|
|
||||||
|
|
|
@ -413,10 +413,12 @@ static void
|
||||||
t_bootstrap(void *boot_raw)
|
t_bootstrap(void *boot_raw)
|
||||||
{
|
{
|
||||||
struct bootstate *boot = (struct bootstate *) boot_raw;
|
struct bootstate *boot = (struct bootstate *) boot_raw;
|
||||||
PyGILState_STATE gstate;
|
PyThreadState *tstate;
|
||||||
PyObject *res;
|
PyObject *res;
|
||||||
|
|
||||||
gstate = PyGILState_Ensure();
|
tstate = PyThreadState_New(boot->interp);
|
||||||
|
|
||||||
|
PyEval_AcquireThread(tstate);
|
||||||
res = PyEval_CallObjectWithKeywords(
|
res = PyEval_CallObjectWithKeywords(
|
||||||
boot->func, boot->args, boot->keyw);
|
boot->func, boot->args, boot->keyw);
|
||||||
if (res == NULL) {
|
if (res == NULL) {
|
||||||
|
@ -441,7 +443,8 @@ t_bootstrap(void *boot_raw)
|
||||||
Py_DECREF(boot->args);
|
Py_DECREF(boot->args);
|
||||||
Py_XDECREF(boot->keyw);
|
Py_XDECREF(boot->keyw);
|
||||||
PyMem_DEL(boot_raw);
|
PyMem_DEL(boot_raw);
|
||||||
PyGILState_Release(gstate);
|
PyThreadState_Clear(tstate);
|
||||||
|
PyThreadState_DeleteCurrent();
|
||||||
PyThread_exit_thread();
|
PyThread_exit_thread();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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_INIT() (void)(head_mutex || (head_mutex = PyThread_allocate_lock()))
|
||||||
#define HEAD_LOCK() PyThread_acquire_lock(head_mutex, WAIT_LOCK)
|
#define HEAD_LOCK() PyThread_acquire_lock(head_mutex, WAIT_LOCK)
|
||||||
#define HEAD_UNLOCK() PyThread_release_lock(head_mutex)
|
#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
|
#else
|
||||||
#define HEAD_INIT() /* Nothing */
|
#define HEAD_INIT() /* Nothing */
|
||||||
#define HEAD_LOCK() /* Nothing */
|
#define HEAD_LOCK() /* Nothing */
|
||||||
|
@ -47,6 +53,8 @@ static PyInterpreterState *interp_head = NULL;
|
||||||
PyThreadState *_PyThreadState_Current = NULL;
|
PyThreadState *_PyThreadState_Current = NULL;
|
||||||
PyThreadFrameGetter _PyThreadState_GetFrame = NULL;
|
PyThreadFrameGetter _PyThreadState_GetFrame = NULL;
|
||||||
|
|
||||||
|
static void _PyGILState_NoteThreadState(PyThreadState* tstate);
|
||||||
|
|
||||||
|
|
||||||
PyInterpreterState *
|
PyInterpreterState *
|
||||||
PyInterpreterState_New(void)
|
PyInterpreterState_New(void)
|
||||||
|
@ -180,6 +188,8 @@ PyThreadState_New(PyInterpreterState *interp)
|
||||||
tstate->c_profileobj = NULL;
|
tstate->c_profileobj = NULL;
|
||||||
tstate->c_traceobj = NULL;
|
tstate->c_traceobj = NULL;
|
||||||
|
|
||||||
|
_PyGILState_NoteThreadState(tstate);
|
||||||
|
|
||||||
HEAD_LOCK();
|
HEAD_LOCK();
|
||||||
tstate->next = interp->tstate_head;
|
tstate->next = interp->tstate_head;
|
||||||
interp->tstate_head = tstate;
|
interp->tstate_head = tstate;
|
||||||
|
@ -261,6 +271,8 @@ PyThreadState_DeleteCurrent()
|
||||||
"PyThreadState_DeleteCurrent: no current tstate");
|
"PyThreadState_DeleteCurrent: no current tstate");
|
||||||
_PyThreadState_Current = NULL;
|
_PyThreadState_Current = NULL;
|
||||||
tstate_delete_common(tstate);
|
tstate_delete_common(tstate);
|
||||||
|
if (autoTLSkey && PyThread_get_key_value(autoTLSkey) == tstate)
|
||||||
|
PyThread_delete_key_value(autoTLSkey);
|
||||||
PyEval_ReleaseLock();
|
PyEval_ReleaseLock();
|
||||||
}
|
}
|
||||||
#endif /* WITH_THREAD */
|
#endif /* WITH_THREAD */
|
||||||
|
@ -393,12 +405,6 @@ PyThreadState_IsCurrent(PyThreadState *tstate)
|
||||||
return tstate == _PyThreadState_Current;
|
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
|
/* Internal initialization/finalization functions called by
|
||||||
Py_Initialize/Py_Finalize
|
Py_Initialize/Py_Finalize
|
||||||
*/
|
*/
|
||||||
|
@ -408,12 +414,10 @@ _PyGILState_Init(PyInterpreterState *i, PyThreadState *t)
|
||||||
assert(i && t); /* must init with valid states */
|
assert(i && t); /* must init with valid states */
|
||||||
autoTLSkey = PyThread_create_key();
|
autoTLSkey = PyThread_create_key();
|
||||||
autoInterpreterState = i;
|
autoInterpreterState = i;
|
||||||
/* Now stash the thread state for this thread in TLS */
|
|
||||||
assert(PyThread_get_key_value(autoTLSkey) == NULL);
|
assert(PyThread_get_key_value(autoTLSkey) == NULL);
|
||||||
if (PyThread_set_key_value(autoTLSkey, (void *)t) < 0)
|
assert(t->gilstate_counter == 0);
|
||||||
Py_FatalError("Couldn't create autoTLSkey mapping");
|
|
||||||
assert(t->gilstate_counter == 0); /* must be a new thread state */
|
_PyGILState_NoteThreadState(t);
|
||||||
t->gilstate_counter = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -424,6 +428,41 @@ _PyGILState_Fini(void)
|
||||||
autoInterpreterState = NULL;;
|
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 */
|
/* The public functions */
|
||||||
PyThreadState *
|
PyThreadState *
|
||||||
PyGILState_GetThisThreadState(void)
|
PyGILState_GetThisThreadState(void)
|
||||||
|
@ -450,8 +489,9 @@ PyGILState_Ensure(void)
|
||||||
tcur = PyThreadState_New(autoInterpreterState);
|
tcur = PyThreadState_New(autoInterpreterState);
|
||||||
if (tcur == NULL)
|
if (tcur == NULL)
|
||||||
Py_FatalError("Couldn't create thread-state for new thread");
|
Py_FatalError("Couldn't create thread-state for new thread");
|
||||||
if (PyThread_set_key_value(autoTLSkey, (void *)tcur) < 0)
|
/* This is our thread state! We'll need to delete it in the
|
||||||
Py_FatalError("Couldn't create autoTLSkey mapping");
|
matching call to PyGILState_Release(). */
|
||||||
|
tcur->gilstate_counter = 0;
|
||||||
current = 0; /* new thread state is never current */
|
current = 0; /* new thread state is never current */
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -498,8 +538,6 @@ PyGILState_Release(PyGILState_STATE oldstate)
|
||||||
* habit of coming back).
|
* habit of coming back).
|
||||||
*/
|
*/
|
||||||
PyThreadState_DeleteCurrent();
|
PyThreadState_DeleteCurrent();
|
||||||
/* Delete this thread from our TLS. */
|
|
||||||
PyThread_delete_key_value(autoTLSkey);
|
|
||||||
}
|
}
|
||||||
/* Release the lock if necessary */
|
/* Release the lock if necessary */
|
||||||
else if (oldstate == PyGILState_UNLOCKED)
|
else if (oldstate == PyGILState_UNLOCKED)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue