diff options
author | Kumar Aditya <59607654+kumaraditya303@users.noreply.github.com> | 2023-01-11 10:33:31 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-01-11 10:33:31 (GMT) |
commit | 762745a124cbc297cf2fe6f3ec9ca1840bb2e873 (patch) | |
tree | afda022491baf91db77ddd5909833e91cb166aee /Modules/_testcapimodule.c | |
parent | 847d7708ba8739a5d5d31f22d71497527a7d8241 (diff) | |
download | cpython-762745a124cbc297cf2fe6f3ec9ca1840bb2e873.zip cpython-762745a124cbc297cf2fe6f3ec9ca1840bb2e873.tar.gz cpython-762745a124cbc297cf2fe6f3ec9ca1840bb2e873.tar.bz2 |
GH-100892: Fix race in clearing `threading.local` (#100922)
Diffstat (limited to 'Modules/_testcapimodule.c')
-rw-r--r-- | Modules/_testcapimodule.c | 41 |
1 files changed, 36 insertions, 5 deletions
diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index c777c3e..486988b 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -1879,12 +1879,19 @@ temporary_c_thread(void *data) PyThread_release_lock(test_c_thread->exit_event); } +static test_c_thread_t test_c_thread; + static PyObject * -call_in_temporary_c_thread(PyObject *self, PyObject *callback) +call_in_temporary_c_thread(PyObject *self, PyObject *args) { PyObject *res = NULL; - test_c_thread_t test_c_thread; + PyObject *callback = NULL; long thread; + int wait = 1; + if (!PyArg_ParseTuple(args, "O|i", &callback, &wait)) + { + return NULL; + } test_c_thread.start_event = PyThread_allocate_lock(); test_c_thread.exit_event = PyThread_allocate_lock(); @@ -1910,6 +1917,10 @@ call_in_temporary_c_thread(PyObject *self, PyObject *callback) PyThread_acquire_lock(test_c_thread.start_event, 1); PyThread_release_lock(test_c_thread.start_event); + if (!wait) { + Py_RETURN_NONE; + } + Py_BEGIN_ALLOW_THREADS PyThread_acquire_lock(test_c_thread.exit_event, 1); PyThread_release_lock(test_c_thread.exit_event); @@ -1919,13 +1930,32 @@ call_in_temporary_c_thread(PyObject *self, PyObject *callback) exit: Py_CLEAR(test_c_thread.callback); - if (test_c_thread.start_event) + if (test_c_thread.start_event) { PyThread_free_lock(test_c_thread.start_event); - if (test_c_thread.exit_event) + test_c_thread.start_event = NULL; + } + if (test_c_thread.exit_event) { PyThread_free_lock(test_c_thread.exit_event); + test_c_thread.exit_event = NULL; + } return res; } +static PyObject * +join_temporary_c_thread(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + Py_BEGIN_ALLOW_THREADS + PyThread_acquire_lock(test_c_thread.exit_event, 1); + PyThread_release_lock(test_c_thread.exit_event); + Py_END_ALLOW_THREADS + Py_CLEAR(test_c_thread.callback); + PyThread_free_lock(test_c_thread.start_event); + test_c_thread.start_event = NULL; + PyThread_free_lock(test_c_thread.exit_event); + test_c_thread.exit_event = NULL; + Py_RETURN_NONE; +} + /* marshal */ static PyObject* @@ -3275,8 +3305,9 @@ static PyMethodDef TestMethods[] = { METH_VARARGS | METH_KEYWORDS}, {"with_tp_del", with_tp_del, METH_VARARGS}, {"create_cfunction", create_cfunction, METH_NOARGS}, - {"call_in_temporary_c_thread", call_in_temporary_c_thread, METH_O, + {"call_in_temporary_c_thread", call_in_temporary_c_thread, METH_VARARGS, PyDoc_STR("set_error_class(error_class) -> None")}, + {"join_temporary_c_thread", join_temporary_c_thread, METH_NOARGS}, {"pymarshal_write_long_to_file", pymarshal_write_long_to_file, METH_VARARGS}, {"pymarshal_write_object_to_file", |