gh-110014: Fix _POSIX_THREADS and _POSIX_SEMAPHORES usage (#110139)

* pycore_pythread.h is now the central place to make sure that
  _POSIX_THREADS and _POSIX_SEMAPHORES macros are defined if
  available.
* Make sure that pycore_pythread.h is included when _POSIX_THREADS
  and _POSIX_SEMAPHORES macros are tested.
* PY_TIMEOUT_MAX is now defined as a constant, since its value
  depends on _POSIX_THREADS, instead of being defined as a macro.
* Prevent integer overflow in the preprocessor when computing
  PY_TIMEOUT_MAX_VALUE on Windows:
  replace "0xFFFFFFFELL * 1000 < LLONG_MAX"
  with "0xFFFFFFFELL < LLONG_MAX / 1000".
* Document the change and give hints how to fix affected code.
* Add an exception for PY_TIMEOUT_MAX  name to smelly.py
* Add PY_TIMEOUT_MAX to the stable ABI
This commit is contained in:
Victor Stinner 2023-09-30 19:25:54 +02:00 committed by GitHub
parent f3bb00ea12
commit 74e425ec18
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 72 additions and 57 deletions

View file

@ -5,18 +5,8 @@
# error "this header requires Py_BUILD_CORE define"
#endif
#ifndef MS_WINDOWS
# include <unistd.h> // _POSIX_THREADS
#endif
#include "pycore_pythread.h" // _POSIX_THREADS
#ifndef _POSIX_THREADS
/* This means pthreads are not implemented in libc headers, hence the macro
not present in unistd.h. But they still can be implemented as an external
library (e.g. gnu pth in pthread emulation) */
# ifdef HAVE_PTHREAD_H
# include <pthread.h> // _POSIX_THREADS
# endif
#endif
#ifdef _POSIX_THREADS
/*

View file

@ -9,29 +9,29 @@ extern "C" {
#endif
#ifndef _POSIX_THREADS
/* This means pthreads are not implemented in libc headers, hence the macro
not present in unistd.h. But they still can be implemented as an external
library (e.g. gnu pth in pthread emulation) */
# ifdef HAVE_PTHREAD_H
# include <pthread.h> // _POSIX_THREADS
# endif
# ifndef _POSIX_THREADS
/* Check if we're running on HP-UX and _SC_THREADS is defined. If so, then
enough of the Posix threads package is implemented to support python
threads.
// Get _POSIX_THREADS and _POSIX_SEMAPHORES macros if available
#if (defined(HAVE_UNISTD_H) && !defined(_POSIX_THREADS) \
&& !defined(_POSIX_SEMAPHORES))
# include <unistd.h> // _POSIX_THREADS, _POSIX_SEMAPHORES
#endif
#if (defined(HAVE_PTHREAD_H) && !defined(_POSIX_THREADS) \
&& !defined(_POSIX_SEMAPHORES))
// This means pthreads are not implemented in libc headers, hence the macro
// not present in <unistd.h>. But they still can be implemented as an
// external library (e.g. gnu pth in pthread emulation)
# include <pthread.h> // _POSIX_THREADS, _POSIX_SEMAPHORES
#endif
#if !defined(_POSIX_THREADS) && defined(__hpux) && defined(_SC_THREADS)
// Check if we're running on HP-UX and _SC_THREADS is defined. If so, then
// enough of the POSIX threads package is implemented to support Python
// threads.
//
// This is valid for HP-UX 11.23 running on an ia64 system. If needed, add
// a check of __ia64 to verify that we're running on an ia64 system instead
// of a pa-risc system.
# define _POSIX_THREADS
#endif
This is valid for HP-UX 11.23 running on an ia64 system. If needed, add
a check of __ia64 to verify that we're running on an ia64 system instead
of a pa-risc system.
*/
# ifdef __hpux
# ifdef _SC_THREADS
# define _POSIX_THREADS
# endif
# endif
# endif /* _POSIX_THREADS */
#endif /* _POSIX_THREADS */
#if defined(_POSIX_THREADS) || defined(HAVE_PTHREAD_STUBS)
# define _USE_PTHREADS

View file

@ -7,7 +7,8 @@
# error "this header requires Py_BUILD_CORE define"
#endif
#include "pycore_time.h" // _PyTime_t
#include "pycore_pythread.h" // _POSIX_SEMAPHORES
#include "pycore_time.h" // _PyTime_t
#ifdef MS_WINDOWS
# define WIN32_LEAN_AND_MEAN
@ -26,6 +27,7 @@
# include <semaphore.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif

View file

@ -44,22 +44,7 @@ PyAPI_FUNC(int) PyThread_acquire_lock(PyThread_type_lock, int);
*/
#define PY_TIMEOUT_T long long
#if defined(_POSIX_THREADS)
/* PyThread_acquire_lock_timed() uses _PyTime_FromNanoseconds(us * 1000),
convert microseconds to nanoseconds. */
# define PY_TIMEOUT_MAX (LLONG_MAX / 1000)
#elif defined (NT_THREADS)
// WaitForSingleObject() accepts timeout in milliseconds in the range
// [0; 0xFFFFFFFE] (DWORD type). INFINITE value (0xFFFFFFFF) means no
// timeout. 0xFFFFFFFE milliseconds is around 49.7 days.
# if 0xFFFFFFFELL * 1000 < LLONG_MAX
# define PY_TIMEOUT_MAX (0xFFFFFFFELL * 1000)
# else
# define PY_TIMEOUT_MAX LLONG_MAX
# endif
#else
# define PY_TIMEOUT_MAX LLONG_MAX
#endif
PyAPI_DATA(const long long) PY_TIMEOUT_MAX;
/* If microseconds == 0, the call is non-blocking: it returns immediately