diff options
author | Gregory P. Smith <greg@krypto.org> | 2022-12-29 22:41:39 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-12-29 22:41:39 (GMT) |
commit | 894f2c3c161933bd820ad322b3b678d89bc2377c (patch) | |
tree | 9c41c6fe2ce16ab42d7fc35223eeca1c061ea269 /Modules/_testcapimodule.c | |
parent | 2df82db48506e5a2044a28f147fdb42f662d37b9 (diff) | |
download | cpython-894f2c3c161933bd820ad322b3b678d89bc2377c.zip cpython-894f2c3c161933bd820ad322b3b678d89bc2377c.tar.gz cpython-894f2c3c161933bd820ad322b3b678d89bc2377c.tar.bz2 |
gh-100228: Warn from os.fork() if other threads exist. (#100229)
Not comprehensive, best effort warning. There are cases when threads exist on some platforms that this code cannot detect. macOS when API permissions allow and Linux with a readable /proc procfs present are the currently supported cases where a warning should show up reliably.
Starting with a DeprecationWarning for now, it is less disruptive than something like RuntimeWarning and most likely to only be seen in people's CI tests - a good place to start with this messaging.
Diffstat (limited to 'Modules/_testcapimodule.c')
-rw-r--r-- | Modules/_testcapimodule.c | 47 |
1 files changed, 47 insertions, 0 deletions
diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index c32fdb5..c777c3e 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -25,6 +25,9 @@ #include "structmember.h" // for offsetof(), T_OBJECT #include <float.h> // FLT_MAX #include <signal.h> +#ifndef MS_WINDOWS +#include <unistd.h> +#endif #ifdef HAVE_SYS_WAIT_H #include <sys/wait.h> // W_STOPCODE @@ -871,6 +874,46 @@ test_thread_state(PyObject *self, PyObject *args) Py_RETURN_NONE; } +#ifndef MS_WINDOWS +static PyThread_type_lock wait_done = NULL; + +static void wait_for_lock(void *unused) { + PyThread_acquire_lock(wait_done, 1); + PyThread_release_lock(wait_done); + PyThread_free_lock(wait_done); + wait_done = NULL; +} + +// These can be used to test things that care about the existence of another +// thread that the threading module doesn't know about. + +static PyObject * +spawn_pthread_waiter(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + if (wait_done) { + PyErr_SetString(PyExc_RuntimeError, "thread already running"); + return NULL; + } + wait_done = PyThread_allocate_lock(); + if (wait_done == NULL) + return PyErr_NoMemory(); + PyThread_acquire_lock(wait_done, 1); + PyThread_start_new_thread(wait_for_lock, NULL); + Py_RETURN_NONE; +} + +static PyObject * +end_spawned_pthread(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + if (!wait_done) { + PyErr_SetString(PyExc_RuntimeError, "call _spawn_pthread_waiter 1st"); + return NULL; + } + PyThread_release_lock(wait_done); + Py_RETURN_NONE; +} +#endif // not MS_WINDOWS + /* test Py_AddPendingCalls using threads */ static int _pending_callback(void *arg) { @@ -3207,6 +3250,10 @@ static PyMethodDef TestMethods[] = { {"test_get_type_name", test_get_type_name, METH_NOARGS}, {"test_get_type_qualname", test_get_type_qualname, METH_NOARGS}, {"_test_thread_state", test_thread_state, METH_VARARGS}, +#ifndef MS_WINDOWS + {"_spawn_pthread_waiter", spawn_pthread_waiter, METH_NOARGS}, + {"_end_spawned_pthread", end_spawned_pthread, METH_NOARGS}, +#endif {"_pending_threadfunc", pending_threadfunc, METH_VARARGS}, #ifdef HAVE_GETTIMEOFDAY {"profile_int", profile_int, METH_NOARGS}, |