From 4d0d1c3866cc408ff3382a9a0220ac0e4f2b3b34 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 2 Oct 2023 18:07:56 +0200 Subject: [PATCH] gh-110014: Remove PY_TIMEOUT_MAX from limited C API (#110217) If the timeout is greater than PY_TIMEOUT_MAX, PyThread_acquire_lock_timed() uses a timeout of PY_TIMEOUT_MAX microseconds, which is around 280.6 years. This case is unlikely and limiting a timeout to 280.6 years sounds like a reasonable trade-off. The constant PY_TIMEOUT_MAX is not used in PyPI top 5,000 projects. --- Doc/data/stable_abi.dat | 1 - Doc/whatsnew/3.13.rst | 3 +++ Include/cpython/pythread.h | 8 ++++++++ Include/pythread.h | 17 ++++------------- Lib/test/test_stable_abi_ctypes.py | 1 - ...23-10-02-13-39-57.gh-issue-110014.gfQ4jU.rst | 2 ++ Misc/stable_abi.toml | 4 ---- PC/python3dll.c | 1 - 8 files changed, 17 insertions(+), 20 deletions(-) create mode 100644 Misc/NEWS.d/next/C API/2023-10-02-13-39-57.gh-issue-110014.gfQ4jU.rst diff --git a/Doc/data/stable_abi.dat b/Doc/data/stable_abi.dat index 07c6d514d19549..c189c78238f40f 100644 --- a/Doc/data/stable_abi.dat +++ b/Doc/data/stable_abi.dat @@ -1,5 +1,4 @@ role,name,added,ifdef_note,struct_abi_kind -var,PY_TIMEOUT_MAX,3.2,, macro,PY_VECTORCALL_ARGUMENTS_OFFSET,3.12,, function,PyAIter_Check,3.10,, function,PyArg_Parse,3.2,, diff --git a/Doc/whatsnew/3.13.rst b/Doc/whatsnew/3.13.rst index 1de5479a924375..3a1b283a75bf2e 100644 --- a/Doc/whatsnew/3.13.rst +++ b/Doc/whatsnew/3.13.rst @@ -1290,3 +1290,6 @@ removed, although there is currently no date scheduled for their removal. * :c:func:`PyThread_get_key_value`: use :c:func:`PyThread_tss_get`. * :c:func:`PyThread_delete_key_value`: use :c:func:`PyThread_tss_delete`. * :c:func:`PyThread_ReInitTLS`: no longer needed. + +* Remove undocumented ``PY_TIMEOUT_MAX`` constant from the limited C API. + (Contributed by Victor Stinner in :gh:`110014`.) diff --git a/Include/cpython/pythread.h b/Include/cpython/pythread.h index cd2aab72d52df3..03f710a9f7ef2e 100644 --- a/Include/cpython/pythread.h +++ b/Include/cpython/pythread.h @@ -2,6 +2,14 @@ # error "this header file must not be included directly" #endif +// PY_TIMEOUT_MAX is the highest usable value (in microseconds) of PY_TIMEOUT_T +// type, and depends on the system threading API. +// +// NOTE: this isn't the same value as `_thread.TIMEOUT_MAX`. The _thread module +// exposes a higher-level API, with timeouts expressed in seconds and +// floating-point numbers allowed. +PyAPI_DATA(const long long) PY_TIMEOUT_MAX; + #define PYTHREAD_INVALID_THREAD_ID ((unsigned long)-1) #ifdef HAVE_PTHREAD_H diff --git a/Include/pythread.h b/Include/pythread.h index 2c2fd63d724286..0784f6b2e5391f 100644 --- a/Include/pythread.h +++ b/Include/pythread.h @@ -33,27 +33,18 @@ PyAPI_FUNC(int) PyThread_acquire_lock(PyThread_type_lock, int); #define WAIT_LOCK 1 #define NOWAIT_LOCK 0 -/* PY_TIMEOUT_T is the integral type used to specify timeouts when waiting - on a lock (see PyThread_acquire_lock_timed() below). - PY_TIMEOUT_MAX is the highest usable value (in microseconds) of that - type, and depends on the system threading API. - - NOTE: this isn't the same value as `_thread.TIMEOUT_MAX`. The _thread - module exposes a higher-level API, with timeouts expressed in seconds - and floating-point numbers allowed. -*/ +// PY_TIMEOUT_T is the integral type used to specify timeouts when waiting +// on a lock (see PyThread_acquire_lock_timed() below). #define PY_TIMEOUT_T long long -PyAPI_DATA(const long long) PY_TIMEOUT_MAX; - /* If microseconds == 0, the call is non-blocking: it returns immediately even when the lock can't be acquired. If microseconds > 0, the call waits up to the specified duration. If microseconds < 0, the call waits until success (or abnormal failure) - microseconds must be less than PY_TIMEOUT_MAX. Behaviour otherwise is - undefined. + If *microseconds* is greater than PY_TIMEOUT_MAX, clamp the timeout to + PY_TIMEOUT_MAX microseconds. If intr_flag is true and the acquire is interrupted by a signal, then the call will return PY_LOCK_INTR. The caller may reattempt to acquire the diff --git a/Lib/test/test_stable_abi_ctypes.py b/Lib/test/test_stable_abi_ctypes.py index 6e9496d40da477..94f817f8e1d159 100644 --- a/Lib/test/test_stable_abi_ctypes.py +++ b/Lib/test/test_stable_abi_ctypes.py @@ -35,7 +35,6 @@ def test_windows_feature_macros(self): SYMBOL_NAMES = ( - "PY_TIMEOUT_MAX", "PyAIter_Check", "PyArg_Parse", "PyArg_ParseTuple", diff --git a/Misc/NEWS.d/next/C API/2023-10-02-13-39-57.gh-issue-110014.gfQ4jU.rst b/Misc/NEWS.d/next/C API/2023-10-02-13-39-57.gh-issue-110014.gfQ4jU.rst new file mode 100644 index 00000000000000..3a5ff7d43bbc01 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2023-10-02-13-39-57.gh-issue-110014.gfQ4jU.rst @@ -0,0 +1,2 @@ +Remove undocumented ``PY_TIMEOUT_MAX`` constant from the limited C API. +Patch by Victor Stinner. diff --git a/Misc/stable_abi.toml b/Misc/stable_abi.toml index 46e2307614e26d..8df3f85e61eec6 100644 --- a/Misc/stable_abi.toml +++ b/Misc/stable_abi.toml @@ -1843,10 +1843,6 @@ [function.PyThread_start_new_thread] added = '3.2' -# Not mentioned in PEP 384, was implemented as a macro in Python <= 3.12 -[data.PY_TIMEOUT_MAX] - added = '3.2' - # The following were added in PC/python3.def in Python 3.3: # 7800f75827b1be557be16f3b18f5170fbf9fae08 # 9c56409d3353b8cd4cfc19e0467bbe23fd34fc92 diff --git a/PC/python3dll.c b/PC/python3dll.c index 75728c7d8057ed..2c1cc8098ce856 100755 --- a/PC/python3dll.c +++ b/PC/python3dll.c @@ -768,7 +768,6 @@ EXPORT_DATA(Py_FileSystemDefaultEncodeErrors) EXPORT_DATA(Py_FileSystemDefaultEncoding) EXPORT_DATA(Py_GenericAliasType) EXPORT_DATA(Py_HasFileSystemDefaultEncoding) -EXPORT_DATA(PY_TIMEOUT_MAX) EXPORT_DATA(Py_UTF8Mode) EXPORT_DATA(Py_Version) EXPORT_DATA(PyBaseObject_Type)