summaryrefslogtreecommitdiffstats
path: root/Include
diff options
context:
space:
mode:
authorAntoine Pitrou <antoine@python.org>2023-11-04 13:59:24 (GMT)
committerGitHub <noreply@github.com>2023-11-04 13:59:24 (GMT)
commit0e9c364f4ac18a2237bdbac702b96bcf8ef9cb09 (patch)
tree8febb8282c2c1ebd73a18205ec5b9229a99ac4fe /Include
parenta28a3967ab9a189122f895d51d2551f7b3a273b0 (diff)
downloadcpython-0e9c364f4ac18a2237bdbac702b96bcf8ef9cb09.zip
cpython-0e9c364f4ac18a2237bdbac702b96bcf8ef9cb09.tar.gz
cpython-0e9c364f4ac18a2237bdbac702b96bcf8ef9cb09.tar.bz2
GH-110829: Ensure Thread.join() joins the OS thread (#110848)
Joining a thread now ensures the underlying OS thread has exited. This is required for safer fork() in multi-threaded processes. --------- Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com>
Diffstat (limited to 'Include')
-rw-r--r--Include/cpython/pthread_stubs.h1
-rw-r--r--Include/internal/pycore_pythread.h42
2 files changed, 43 insertions, 0 deletions
diff --git a/Include/cpython/pthread_stubs.h b/Include/cpython/pthread_stubs.h
index 5246968..e542eaa 100644
--- a/Include/cpython/pthread_stubs.h
+++ b/Include/cpython/pthread_stubs.h
@@ -83,6 +83,7 @@ PyAPI_FUNC(int) pthread_create(pthread_t *restrict thread,
void *(*start_routine)(void *),
void *restrict arg);
PyAPI_FUNC(int) pthread_detach(pthread_t thread);
+PyAPI_FUNC(int) pthread_join(pthread_t thread, void** value_ptr);
PyAPI_FUNC(pthread_t) pthread_self(void);
PyAPI_FUNC(int) pthread_exit(void *retval) __attribute__ ((__noreturn__));
PyAPI_FUNC(int) pthread_attr_init(pthread_attr_t *attr);
diff --git a/Include/internal/pycore_pythread.h b/Include/internal/pycore_pythread.h
index d31ffc7..9c9a09f 100644
--- a/Include/internal/pycore_pythread.h
+++ b/Include/internal/pycore_pythread.h
@@ -106,6 +106,48 @@ PyAPI_FUNC(PyLockStatus) PyThread_acquire_lock_timed_with_retries(
PyThread_type_lock,
PY_TIMEOUT_T microseconds);
+typedef unsigned long long PyThread_ident_t;
+typedef Py_uintptr_t PyThread_handle_t;
+
+#define PY_FORMAT_THREAD_IDENT_T "llu"
+#define Py_PARSE_THREAD_IDENT_T "K"
+
+PyAPI_FUNC(PyThread_ident_t) PyThread_get_thread_ident_ex(void);
+
+/* Thread joining APIs.
+ *
+ * These APIs have a strict contract:
+ * - Either PyThread_join_thread or PyThread_detach_thread must be called
+ * exactly once with the given handle.
+ * - Calling neither PyThread_join_thread nor PyThread_detach_thread results
+ * in a resource leak until the end of the process.
+ * - Any other usage, such as calling both PyThread_join_thread and
+ * PyThread_detach_thread, or calling them more than once (including
+ * simultaneously), results in undefined behavior.
+ */
+PyAPI_FUNC(int) PyThread_start_joinable_thread(void (*func)(void *),
+ void *arg,
+ PyThread_ident_t* ident,
+ PyThread_handle_t* handle);
+/*
+ * Join a thread started with `PyThread_start_joinable_thread`.
+ * This function cannot be interrupted. It returns 0 on success,
+ * a non-zero value on failure.
+ */
+PyAPI_FUNC(int) PyThread_join_thread(PyThread_handle_t);
+/*
+ * Detach a thread started with `PyThread_start_joinable_thread`, such
+ * that its resources are relased as soon as it exits.
+ * This function cannot be interrupted. It returns 0 on success,
+ * a non-zero value on failure.
+ */
+PyAPI_FUNC(int) PyThread_detach_thread(PyThread_handle_t);
+
+/*
+ * Obtain the new thread ident and handle in a forked child process.
+ */
+PyAPI_FUNC(void) PyThread_update_thread_after_fork(PyThread_ident_t* ident,
+ PyThread_handle_t* handle);
#ifdef __cplusplus
}