Skip to content

gh-110014: Fix _POSIX_THREADS and _POSIX_SEMAPHORES usage #110139

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Sep 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Doc/data/stable_abi.dat

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions Doc/whatsnew/3.13.rst
Original file line number Diff line number Diff line change
Expand Up @@ -989,6 +989,10 @@ Porting to Python 3.13
* ``Python.h`` no longer includes the ``<unistd.h>`` standard header file. If
needed, it should now be included explicitly. For example, it provides the
functions: ``close()``, ``getpagesize()``, ``getpid()`` and ``sysconf()``.
As a consequence, ``_POSIX_SEMAPHORES`` and ``_POSIX_THREADS`` macros are no
longer defined by ``Python.h``. The ``HAVE_UNISTD_H`` and ``HAVE_PTHREAD_H``
macros defined by ``Python.h`` can be used to decide if ``<unistd.h>`` and
``<pthread.h>`` header files can be included.
(Contributed by Victor Stinner in :gh:`108765`.)

* ``Python.h`` no longer includes these standard header files: ``<time.h>``,
Expand Down
12 changes: 1 addition & 11 deletions Include/internal/pycore_condvar.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
/*
Expand Down
46 changes: 23 additions & 23 deletions Include/internal/pycore_pythread.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.

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 */
// 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


#if defined(_POSIX_THREADS) || defined(HAVE_PTHREAD_STUBS)
# define _USE_PTHREADS
Expand Down
4 changes: 3 additions & 1 deletion Include/internal/pycore_semaphore.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -26,6 +27,7 @@
# include <semaphore.h>
#endif


#ifdef __cplusplus
extern "C" {
#endif
Expand Down
17 changes: 1 addition & 16 deletions Include/pythread.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions Lib/test/test_stable_abi_ctypes.py

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions Misc/stable_abi.toml
Original file line number Diff line number Diff line change
Expand Up @@ -1843,6 +1843,10 @@
[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]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vstinner Could we instead exclude this undocumented constant from the limited API?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I checked and apparently, it's safe to remove this constant, so I created PR gh-110217 for that.

added = '3.2'

# The following were added in PC/python3.def in Python 3.3:
# 7800f75827b1be557be16f3b18f5170fbf9fae08
# 9c56409d3353b8cd4cfc19e0467bbe23fd34fc92
Expand Down
1 change: 1 addition & 0 deletions PC/python3dll.c

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Python/condvar.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@
#define _CONDVAR_IMPL_H_

#include "Python.h"
#include "pycore_condvar.h"
#include "pycore_pythread.h" // _POSIX_THREADS


#ifdef _POSIX_THREADS
/*
Expand Down
22 changes: 21 additions & 1 deletion Python/thread.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
#include "Python.h"
#include "pycore_pystate.h" // _PyInterpreterState_GET()
#include "pycore_structseq.h" // _PyStructSequence_FiniBuiltin()
#include "pycore_pythread.h"
#include "pycore_pythread.h" // _POSIX_THREADS

#ifndef DONT_HAVE_STDIO_H
# include <stdio.h>
Expand All @@ -17,6 +17,26 @@
#include <stdlib.h>


// Define PY_TIMEOUT_MAX constant.
#ifdef _POSIX_THREADS
// PyThread_acquire_lock_timed() uses _PyTime_FromNanoseconds(us * 1000),
// convert microseconds to nanoseconds.
# define PY_TIMEOUT_MAX_VALUE (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 < LLONG_MAX / 1000
# define PY_TIMEOUT_MAX_VALUE (0xFFFFFFFELL * 1000)
# else
# define PY_TIMEOUT_MAX_VALUE LLONG_MAX
# endif
#else
# define PY_TIMEOUT_MAX_VALUE LLONG_MAX
#endif
const long long PY_TIMEOUT_MAX = PY_TIMEOUT_MAX_VALUE;


static void PyThread__init_thread(void); /* Forward */

#define initialized _PyRuntime.threads.initialized
Expand Down
9 changes: 5 additions & 4 deletions Python/thread_pthread.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "pycore_interp.h" // _PyInterpreterState.threads.stacksize
#include "pycore_interp.h" // _PyInterpreterState.threads.stacksize
#include "pycore_pythread.h" // _POSIX_SEMAPHORES

/* Posix threads interface */

Expand Down Expand Up @@ -84,10 +85,10 @@
/* On FreeBSD 4.x, _POSIX_SEMAPHORES is defined empty, so
we need to add 0 to make it work there as well. */
#if (_POSIX_SEMAPHORES+0) == -1
#define HAVE_BROKEN_POSIX_SEMAPHORES
# define HAVE_BROKEN_POSIX_SEMAPHORES
#else
#include <semaphore.h>
#include <errno.h>
# include <semaphore.h>
# include <errno.h>
#endif
#endif

Expand Down
7 changes: 6 additions & 1 deletion Tools/build/smelly.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@
if sys.platform == 'darwin':
ALLOWED_PREFIXES += ('__Py',)

# "Legacy": some old symbols are prefixed by "PY_".
EXCEPTIONS = frozenset({
'PY_TIMEOUT_MAX',
})

IGNORED_EXTENSION = "_ctypes_test"
# Ignore constructor and destructor functions
IGNORED_SYMBOLS = {'_init', '_fini'}
Expand Down Expand Up @@ -72,7 +77,7 @@ def get_smelly_symbols(stdout):
symbol = parts[-1]
result = '%s (type: %s)' % (symbol, symtype)

if symbol.startswith(ALLOWED_PREFIXES):
if symbol.startswith(ALLOWED_PREFIXES) or symbol in EXCEPTIONS:
python_symbols.append(result)
continue

Expand Down