Skip to content

Commit 19dfaca

Browse files
committed
Add a race test for PyThreadState_EnsureFromView.
1 parent 7703906 commit 19dfaca

2 files changed

Lines changed: 59 additions & 18 deletions

File tree

Lib/test/test_embed.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2002,6 +2002,9 @@ def test_thread_state_ensure(self):
20022002
def test_main_interpreter_view(self):
20032003
self.run_embedded_interpreter("test_main_interpreter_view")
20042004

2005+
def test_thread_state_ensure_from_view(self):
2006+
self.run_embedded_interpreter("test_thread_state_ensure_from_view")
2007+
20052008

20062009
class MiscTests(EmbeddingTestsMixin, unittest.TestCase):
20072010
def test_unicode_id_init(self):

Programs/_testembed.c

Lines changed: 56 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2682,32 +2682,34 @@ const char *THREAD_CODE = \
26822682
"fib(10)";
26832683

26842684
typedef struct {
2685-
PyInterpreterGuard *guard;
2685+
void *argument;
26862686
int done;
2687+
PyEvent event;
26872688
} ThreadData;
26882689

26892690
static void
26902691
do_tstate_ensure(void *arg)
26912692
{
26922693
ThreadData *data = (ThreadData *)arg;
2693-
PyThreadState *refs[4];
2694-
refs[0] = PyThreadState_Ensure(data->guard);
2695-
refs[1] = PyThreadState_Ensure(data->guard);
2696-
refs[2] = PyThreadState_Ensure(data->guard);
2694+
PyThreadState *tstates[4];
2695+
PyInterpreterGuard *guard = data->argument;
2696+
tstates[0] = PyThreadState_Ensure(guard);
2697+
tstates[1] = PyThreadState_Ensure(guard);
2698+
tstates[2] = PyThreadState_Ensure(guard);
26972699
PyGILState_STATE gstate = PyGILState_Ensure();
2698-
refs[3] = PyThreadState_Ensure(data->guard);
2699-
assert(refs[0] != 0);
2700-
assert(refs[1] != 0);
2701-
assert(refs[2] != 0);
2702-
assert(refs[3] != 0);
2700+
tstates[3] = PyThreadState_Ensure(guard);
2701+
assert(tstates[0] != NULL);
2702+
assert(tstates[1] != NULL);
2703+
assert(tstates[2] != NULL);
2704+
assert(tstates[3] != NULL);
27032705
int res = PyRun_SimpleString(THREAD_CODE);
27042706
assert(res == 0);
2705-
PyThreadState_Release(refs[3]);
2707+
PyThreadState_Release(tstates[3]);
27062708
PyGILState_Release(gstate);
2707-
PyThreadState_Release(refs[2]);
2708-
PyThreadState_Release(refs[1]);
2709-
PyThreadState_Release(refs[0]);
2710-
PyInterpreterGuard_Close(data->guard);
2709+
PyThreadState_Release(tstates[2]);
2710+
PyThreadState_Release(tstates[1]);
2711+
PyThreadState_Release(tstates[0]);
2712+
PyInterpreterGuard_Close(guard);
27112713
data->done = 1;
27122714
}
27132715

@@ -2718,9 +2720,7 @@ test_thread_state_ensure(void)
27182720
PyThread_handle_t handle;
27192721
PyThread_ident_t ident;
27202722
PyInterpreterGuard *guard = PyInterpreterGuard_FromCurrent();
2721-
if (guard == NULL) {
2722-
return -1;
2723-
};
2723+
assert(guard != NULL);
27242724
ThreadData data = { guard };
27252725
if (PyThread_start_joinable_thread(do_tstate_ensure, &data,
27262726
&ident, &handle) < 0) {
@@ -2759,6 +2759,43 @@ test_main_interpreter_view(void)
27592759
return 0;
27602760
}
27612761

2762+
static void
2763+
do_tstate_ensure_from_view(void *arg)
2764+
{
2765+
ThreadData *data = (ThreadData *)arg;
2766+
PyInterpreterView *view = data->argument;
2767+
assert(view != NULL);
2768+
PyThreadState *tstate = PyThreadState_EnsureFromView(view);
2769+
assert(tstate != NULL);
2770+
_PyEvent_Notify(&data->event);
2771+
int res = PyRun_SimpleString(THREAD_CODE);
2772+
assert(res == 0);
2773+
data->done = 1;
2774+
PyThreadState_Release(tstate);
2775+
}
2776+
2777+
static int
2778+
test_thread_state_ensure_from_view(void)
2779+
{
2780+
_testembed_initialize();
2781+
PyThread_handle_t handle;
2782+
PyThread_ident_t ident;
2783+
PyInterpreterView *view = PyInterpreterView_FromCurrent();
2784+
assert(view != NULL);
2785+
2786+
ThreadData data = { view };
2787+
if (PyThread_start_joinable_thread(do_tstate_ensure_from_view, &data,
2788+
&ident, &handle) < 0) {
2789+
PyInterpreterView_Close(view);
2790+
return -1;
2791+
}
2792+
2793+
PyEvent_Wait(&data.event);
2794+
Py_Finalize();
2795+
assert(data.done == 1);
2796+
return 0;
2797+
}
2798+
27622799
/* *********************************************************
27632800
* List of test cases and the function that implements it.
27642801
*
@@ -2855,6 +2892,7 @@ static struct TestCase TestCases[] = {
28552892
{"test_inittab_submodule_singlephase", test_inittab_submodule_singlephase},
28562893
{"test_thread_state_ensure", test_thread_state_ensure},
28572894
{"test_main_interpreter_view", test_main_interpreter_view},
2895+
{"test_thread_state_ensure_from_view", test_thread_state_ensure_from_view},
28582896
{NULL, NULL}
28592897
};
28602898

0 commit comments

Comments
 (0)