Skip to content

Commit debd72e

Browse files
author
mwh
committed
Fix bug:
[ 1163563 ] Sub threads execute in restricted mode basically by fixing bug 1010677 in a non-broken way. Backport candidate. git-svn-id: http://svn.python.org/projects/python/trunk@39044 6015fed2-1504-0410-9fe1-9d1591cc4771
1 parent b57709f commit debd72e

3 files changed

Lines changed: 65 additions & 18 deletions

File tree

Misc/NEWS

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@ What's New in Python 2.5 alpha 1?
1212
Core and builtins
1313
-----------------
1414

15+
- SF bug #1163563: the original fix for bug #1010677 ("thread Module
16+
Breaks PyGILState_Ensure()") broke badly in the case of multiple
17+
interpreter states; back out that fix and do a better job (see
18+
http://mail.python.org/pipermail/python-dev/2005-June/054258.html
19+
for a longer write-up of the problem).
20+
1521
- SF patch #1180995: marshal now uses a binary format by default when
1622
serializing floats.
1723

Modules/threadmodule.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -413,10 +413,12 @@ static void
413413
t_bootstrap(void *boot_raw)
414414
{
415415
struct bootstate *boot = (struct bootstate *) boot_raw;
416-
PyGILState_STATE gstate;
416+
PyThreadState *tstate;
417417
PyObject *res;
418418

419-
gstate = PyGILState_Ensure();
419+
tstate = PyThreadState_New(boot->interp);
420+
421+
PyEval_AcquireThread(tstate);
420422
res = PyEval_CallObjectWithKeywords(
421423
boot->func, boot->args, boot->keyw);
422424
if (res == NULL) {
@@ -441,7 +443,8 @@ t_bootstrap(void *boot_raw)
441443
Py_DECREF(boot->args);
442444
Py_XDECREF(boot->keyw);
443445
PyMem_DEL(boot_raw);
444-
PyGILState_Release(gstate);
446+
PyThreadState_Clear(tstate);
447+
PyThreadState_DeleteCurrent();
445448
PyThread_exit_thread();
446449
}
447450

Python/pystate.c

Lines changed: 53 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,12 @@ static PyThread_type_lock head_mutex = NULL; /* Protects interp->tstate_head */
3636
#define HEAD_INIT() (void)(head_mutex || (head_mutex = PyThread_allocate_lock()))
3737
#define HEAD_LOCK() PyThread_acquire_lock(head_mutex, WAIT_LOCK)
3838
#define HEAD_UNLOCK() PyThread_release_lock(head_mutex)
39+
40+
/* The single PyInterpreterState used by this process'
41+
GILState implementation
42+
*/
43+
static PyInterpreterState *autoInterpreterState = NULL;
44+
static int autoTLSkey = 0;
3945
#else
4046
#define HEAD_INIT() /* Nothing */
4147
#define HEAD_LOCK() /* Nothing */
@@ -47,6 +53,8 @@ static PyInterpreterState *interp_head = NULL;
4753
PyThreadState *_PyThreadState_Current = NULL;
4854
PyThreadFrameGetter _PyThreadState_GetFrame = NULL;
4955

56+
static void _PyGILState_NoteThreadState(PyThreadState* tstate);
57+
5058

5159
PyInterpreterState *
5260
PyInterpreterState_New(void)
@@ -180,6 +188,8 @@ PyThreadState_New(PyInterpreterState *interp)
180188
tstate->c_profileobj = NULL;
181189
tstate->c_traceobj = NULL;
182190

191+
_PyGILState_NoteThreadState(tstate);
192+
183193
HEAD_LOCK();
184194
tstate->next = interp->tstate_head;
185195
interp->tstate_head = tstate;
@@ -261,6 +271,8 @@ PyThreadState_DeleteCurrent()
261271
"PyThreadState_DeleteCurrent: no current tstate");
262272
_PyThreadState_Current = NULL;
263273
tstate_delete_common(tstate);
274+
if (autoTLSkey && PyThread_get_key_value(autoTLSkey) == tstate)
275+
PyThread_delete_key_value(autoTLSkey);
264276
PyEval_ReleaseLock();
265277
}
266278
#endif /* WITH_THREAD */
@@ -393,12 +405,6 @@ PyThreadState_IsCurrent(PyThreadState *tstate)
393405
return tstate == _PyThreadState_Current;
394406
}
395407

396-
/* The single PyInterpreterState used by this process'
397-
GILState implementation
398-
*/
399-
static PyInterpreterState *autoInterpreterState = NULL;
400-
static int autoTLSkey = 0;
401-
402408
/* Internal initialization/finalization functions called by
403409
Py_Initialize/Py_Finalize
404410
*/
@@ -408,12 +414,10 @@ _PyGILState_Init(PyInterpreterState *i, PyThreadState *t)
408414
assert(i && t); /* must init with valid states */
409415
autoTLSkey = PyThread_create_key();
410416
autoInterpreterState = i;
411-
/* Now stash the thread state for this thread in TLS */
412417
assert(PyThread_get_key_value(autoTLSkey) == NULL);
413-
if (PyThread_set_key_value(autoTLSkey, (void *)t) < 0)
414-
Py_FatalError("Couldn't create autoTLSkey mapping");
415-
assert(t->gilstate_counter == 0); /* must be a new thread state */
416-
t->gilstate_counter = 1;
418+
assert(t->gilstate_counter == 0);
419+
420+
_PyGILState_NoteThreadState(t);
417421
}
418422

419423
void
@@ -424,6 +428,41 @@ _PyGILState_Fini(void)
424428
autoInterpreterState = NULL;;
425429
}
426430

431+
/* When a thread state is created for a thread by some mechanism other than
432+
PyGILState_Ensure, it's important that the GILState machinery knows about
433+
it so it doesn't try to create another thread state for the thread (this is
434+
a better fix for SF bug #1010677 than the first one attempted).
435+
*/
436+
void
437+
_PyGILState_NoteThreadState(PyThreadState* tstate)
438+
{
439+
/* If autoTLSkey is 0, this must be the very first threadstate created
440+
in Py_Initialize(). Don't do anything for now (we'll be back here
441+
when _PyGILState_Init is called). */
442+
if (!autoTLSkey)
443+
return;
444+
445+
/* Stick the thread state for this thread in thread local storage.
446+
447+
The only situation where you can legitimately have more than one
448+
thread state for an OS level thread is when there are multiple
449+
interpreters, when:
450+
451+
a) You shouldn't really be using the PyGILState_ APIs anyway,
452+
and:
453+
454+
b) The slightly odd way PyThread_set_key_value works (see
455+
comments by its implementation) means that the first thread
456+
state created for that given OS level thread will "win",
457+
which seems reasonable behaviour.
458+
*/
459+
if (PyThread_set_key_value(autoTLSkey, (void *)tstate) < 0)
460+
Py_FatalError("Couldn't create autoTLSkey mapping");
461+
462+
/* PyGILState_Release must not try to delete this thread state. */
463+
tstate->gilstate_counter = 1;
464+
}
465+
427466
/* The public functions */
428467
PyThreadState *
429468
PyGILState_GetThisThreadState(void)
@@ -450,8 +489,9 @@ PyGILState_Ensure(void)
450489
tcur = PyThreadState_New(autoInterpreterState);
451490
if (tcur == NULL)
452491
Py_FatalError("Couldn't create thread-state for new thread");
453-
if (PyThread_set_key_value(autoTLSkey, (void *)tcur) < 0)
454-
Py_FatalError("Couldn't create autoTLSkey mapping");
492+
/* This is our thread state! We'll need to delete it in the
493+
matching call to PyGILState_Release(). */
494+
tcur->gilstate_counter = 0;
455495
current = 0; /* new thread state is never current */
456496
}
457497
else
@@ -498,8 +538,6 @@ PyGILState_Release(PyGILState_STATE oldstate)
498538
* habit of coming back).
499539
*/
500540
PyThreadState_DeleteCurrent();
501-
/* Delete this thread from our TLS. */
502-
PyThread_delete_key_value(autoTLSkey);
503541
}
504542
/* Release the lock if necessary */
505543
else if (oldstate == PyGILState_UNLOCKED)

0 commit comments

Comments
 (0)