From fceec42e495bbe944150b52e34e43ee140652fc7 Mon Sep 17 00:00:00 2001 From: Lawrence D'Anna Date: Mon, 20 Jul 2020 18:01:41 -0700 Subject: [PATCH 1/2] add runtime checks for MACOSX_DEPLOYMENT_TARGET=10.10 In order to support a universal2 build, supporitng Mac OS 11 on arm64 and Mac OS on x86_64 going back to 10.10, we need to add in runtime checks for functions that will be detected as present by autoconf, because they are in the SDK, but which did not exist in Mac OS 10.10. This fixes all the instances of -WWunguarded-availability-new when building with MACOSX_DEPLOYMENT_TARGET=10.10 --- Modules/posixmodule.c | 263 ++++++++++++++++++++--------------- Modules/timemodule.c | 300 ++++++++++++++++++++++++++-------------- Python/bootstrap_hash.c | 30 +++- Python/pytime.c | 89 ++++++------ configure | 35 +++++ configure.ac | 13 ++ pyconfig.h.in | 3 + 7 files changed, 471 insertions(+), 262 deletions(-) diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index efd99544f5a997..277d8b93325c62 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -79,6 +79,26 @@ corresponding Unix manual entries for more information on calls."); # include #endif /* HAVE_SYS_STAT_H */ +#if defined(__APPLE__) +#include +#endif + +#if defined(__APPLE__) && HAVE_BUILTIN_AVAILABLE && !(TARGET_OS_OSX && __arm64__) +#define HAVE_UTIMENSAT_RUNTIME __builtin_available(macos 10.13, ios 11, tvos 11, watchos 4, *) +#define HAVE_FUTIMENS_RUNTIME __builtin_available(macos 10.13, ios 11, tvos 11, watchos 4, *) +#define HAVE_PREADV_RUNTIME __builtin_available(macos 10.16, ios 14, tvos 14, watchos 7, *) +#define HAVE_PWRITEV_RUNTIME __builtin_available(macos 10.16, ios 14, tvos 14, watchos 7, *) +#else +#define HAVE_UTIMENSAT_RUNTIME 1 +#define HAVE_FUTIMENS_RUNTIME 1 +#define HAVE_PREADV_RUNTIME 1 +#define HAVE_PWRITEV_RUNTIME 1 +#endif + +#if defined(__APPLE__) && TARGET_OS_OSX && __arm64__ && __clang__ +#pragma clang diagnostic ignored "-Wunguarded-availability-new" +#endif + #ifdef HAVE_SYS_WAIT_H # include // WNOHANG #endif @@ -4826,9 +4846,13 @@ static int utime_dir_fd(utime_t *ut, int dir_fd, const char *path, int follow_symlinks) { #ifdef HAVE_UTIMENSAT - int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW; - UTIME_TO_TIMESPEC; - return utimensat(dir_fd, path, time, flags); + if (HAVE_UTIMENSAT_RUNTIME) { + int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW; + UTIME_TO_TIMESPEC; + return utimensat(dir_fd, path, time, flags); + } else { + return -1; + } #elif defined(HAVE_FUTIMESAT) UTIME_TO_TIMEVAL; /* @@ -4852,12 +4876,15 @@ static int utime_fd(utime_t *ut, int fd) { #ifdef HAVE_FUTIMENS - UTIME_TO_TIMESPEC; - return futimens(fd, time); -#else - UTIME_TO_TIMEVAL; - return futimes(fd, time); + if (HAVE_FUTIMENS_RUNTIME) { + UTIME_TO_TIMESPEC; + return futimens(fd, time); + } else #endif + { + UTIME_TO_TIMEVAL; + return futimes(fd, time); + } } #define PATH_UTIME_HAVE_FD 1 @@ -4875,12 +4902,15 @@ static int utime_nofollow_symlinks(utime_t *ut, const char *path) { #ifdef HAVE_UTIMENSAT - UTIME_TO_TIMESPEC; - return utimensat(DEFAULT_DIR_FD, path, time, AT_SYMLINK_NOFOLLOW); -#else - UTIME_TO_TIMEVAL; - return lutimes(path, time); + if (HAVE_FUTIMENS_RUNTIME) { + UTIME_TO_TIMESPEC; + return utimensat(DEFAULT_DIR_FD, path, time, AT_SYMLINK_NOFOLLOW); + } else #endif + { + UTIME_TO_TIMEVAL; + return lutimes(path, time); + } } #endif @@ -4891,9 +4921,12 @@ static int utime_default(utime_t *ut, const char *path) { #ifdef HAVE_UTIMENSAT - UTIME_TO_TIMESPEC; - return utimensat(DEFAULT_DIR_FD, path, time, 0); -#elif defined(HAVE_UTIMES) + if (HAVE_UTIMENSAT_RUNTIME) { + UTIME_TO_TIMESPEC; + return utimensat(DEFAULT_DIR_FD, path, time, 0); + } +#endif +#if defined(HAVE_UTIMES) UTIME_TO_TIMEVAL; return utimes(path, time); #elif defined(HAVE_UTIME_H) @@ -5092,6 +5125,10 @@ os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns, #else /* MS_WINDOWS */ Py_BEGIN_ALLOW_THREADS + int have_utimensat_runtime = 0; + if (HAVE_UTIMENSAT_RUNTIME) + have_utimensat_runtime = 1; + #ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD)) result = utime_nofollow_symlinks(&utime, path->narrow); @@ -5099,7 +5136,7 @@ os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns, #endif #if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT) - if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) + if (have_utimensat_runtime && ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks))) result = utime_dir_fd(&utime, dir_fd, path->narrow, follow_symlinks); else #endif @@ -9255,59 +9292,64 @@ os_preadv_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset, int flags) /*[clinic end generated code: output=26fc9c6e58e7ada5 input=4173919dc1f7ed99]*/ { - Py_ssize_t cnt, n; - int async_err = 0; - struct iovec *iov; - Py_buffer *buf; + if (HAVE_PREADV_RUNTIME) { + Py_ssize_t cnt, n; + int async_err = 0; + struct iovec *iov; + Py_buffer *buf; - if (!PySequence_Check(buffers)) { - PyErr_SetString(PyExc_TypeError, - "preadv2() arg 2 must be a sequence"); - return -1; - } + if (!PySequence_Check(buffers)) { + PyErr_SetString(PyExc_TypeError, + "preadv2() arg 2 must be a sequence"); + return -1; + } - cnt = PySequence_Size(buffers); - if (cnt < 0) { - return -1; - } + cnt = PySequence_Size(buffers); + if (cnt < 0) { + return -1; + } -#ifndef HAVE_PREADV2 - if(flags != 0) { - argument_unavailable_error("preadv2", "flags"); - return -1; - } -#endif + #ifndef HAVE_PREADV2 + if(flags != 0) { + argument_unavailable_error("preadv2", "flags"); + return -1; + } + #endif - if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0) { - return -1; - } -#ifdef HAVE_PREADV2 - do { - Py_BEGIN_ALLOW_THREADS - _Py_BEGIN_SUPPRESS_IPH - n = preadv2(fd, iov, cnt, offset, flags); - _Py_END_SUPPRESS_IPH - Py_END_ALLOW_THREADS - } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); -#else - do { - Py_BEGIN_ALLOW_THREADS - _Py_BEGIN_SUPPRESS_IPH - n = preadv(fd, iov, cnt, offset); - _Py_END_SUPPRESS_IPH - Py_END_ALLOW_THREADS - } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); -#endif + if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0) { + return -1; + } + #ifdef HAVE_PREADV2 + do { + Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH + n = preadv2(fd, iov, cnt, offset, flags); + _Py_END_SUPPRESS_IPH + Py_END_ALLOW_THREADS + } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + #else + do { + Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH + n = preadv(fd, iov, cnt, offset); + _Py_END_SUPPRESS_IPH + Py_END_ALLOW_THREADS + } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + #endif - iov_cleanup(iov, buf, cnt); - if (n < 0) { - if (!async_err) { - posix_error(); + iov_cleanup(iov, buf, cnt); + if (n < 0) { + if (!async_err) { + posix_error(); + } + return -1; } + + return n; + } else { + PyErr_SetString(PyExc_NotImplementedError, "preadv is not available"); return -1; } - - return n; } #endif /* HAVE_PREADV */ @@ -9850,60 +9892,65 @@ os_pwritev_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset, int flags) /*[clinic end generated code: output=e3dd3e9d11a6a5c7 input=35358c327e1a2a8e]*/ { - Py_ssize_t cnt; - Py_ssize_t result; - int async_err = 0; - struct iovec *iov; - Py_buffer *buf; + if (HAVE_PWRITEV_RUNTIME) { + Py_ssize_t cnt; + Py_ssize_t result; + int async_err = 0; + struct iovec *iov; + Py_buffer *buf; - if (!PySequence_Check(buffers)) { - PyErr_SetString(PyExc_TypeError, - "pwritev() arg 2 must be a sequence"); - return -1; - } + if (!PySequence_Check(buffers)) { + PyErr_SetString(PyExc_TypeError, + "pwritev() arg 2 must be a sequence"); + return -1; + } - cnt = PySequence_Size(buffers); - if (cnt < 0) { - return -1; - } + cnt = PySequence_Size(buffers); + if (cnt < 0) { + return -1; + } -#ifndef HAVE_PWRITEV2 - if(flags != 0) { - argument_unavailable_error("pwritev2", "flags"); - return -1; - } -#endif + #ifndef HAVE_PWRITEV2 + if(flags != 0) { + argument_unavailable_error("pwritev2", "flags"); + return -1; + } + #endif - if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) { - return -1; - } -#ifdef HAVE_PWRITEV2 - do { - Py_BEGIN_ALLOW_THREADS - _Py_BEGIN_SUPPRESS_IPH - result = pwritev2(fd, iov, cnt, offset, flags); - _Py_END_SUPPRESS_IPH - Py_END_ALLOW_THREADS - } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); -#else - do { - Py_BEGIN_ALLOW_THREADS - _Py_BEGIN_SUPPRESS_IPH - result = pwritev(fd, iov, cnt, offset); - _Py_END_SUPPRESS_IPH - Py_END_ALLOW_THREADS - } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); -#endif + if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) { + return -1; + } + #ifdef HAVE_PWRITEV2 + do { + Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH + result = pwritev2(fd, iov, cnt, offset, flags); + _Py_END_SUPPRESS_IPH + Py_END_ALLOW_THREADS + } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + #else + do { + Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH + result = pwritev(fd, iov, cnt, offset); + _Py_END_SUPPRESS_IPH + Py_END_ALLOW_THREADS + } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + #endif - iov_cleanup(iov, buf, cnt); - if (result < 0) { - if (!async_err) { - posix_error(); + iov_cleanup(iov, buf, cnt); + if (result < 0) { + if (!async_err) { + posix_error(); + } + return -1; } + + return result; + } else { + PyErr_SetString(PyExc_NotImplementedError, "preadv is not available"); return -1; } - - return result; } #endif /* HAVE_PWRITEV */ diff --git a/Modules/timemodule.c b/Modules/timemodule.c index 8a4d149befb52a..96e2486f27da27 100644 --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -51,6 +51,20 @@ #define _Py_tzname tzname #endif +#if defined(__APPLE__) +#include +#endif + +#if defined(__APPLE__) && HAVE_BUILTIN_AVAILABLE && !(TARGET_OS_OSX && __arm64__) +#define HAVE_CLOCK_GETTIME_RUNTIME __builtin_available(macos 10.12, ios 10, tvos 10, watchos 3, *) +#define HAVE_CLOCK_SETTIME_RUNTIME __builtin_available(macos 10.12, ios 10, tvos 10, watchos 3, *) +#define HAVE_CLOCK_GETRES_RUNTIME __builtin_available(macos 10.12, ios 10, tvos 10, watchos 3, *) +#else +#define HAVE_CLOCK_GETTIME_RUNTIME 1 +#define HAVE_CLOCK_SETTIME_RUNTIME 1 +#define HAVE_CLOCK_GETRES_RUNTIME 1 +#endif + #define SEC_TO_NS (1000 * 1000 * 1000) /* Forward declarations */ @@ -152,25 +166,30 @@ perf_counter(_Py_clock_info_t *info) static PyObject * time_clock_gettime(PyObject *self, PyObject *args) { - int ret; - struct timespec tp; - -#if defined(_AIX) && (SIZEOF_LONG == 8) - long clk_id; - if (!PyArg_ParseTuple(args, "l:clock_gettime", &clk_id)) { -#else - int clk_id; - if (!PyArg_ParseTuple(args, "i:clock_gettime", &clk_id)) { -#endif - return NULL; - } + if (HAVE_CLOCK_GETTIME_RUNTIME) { + int ret; + struct timespec tp; + + #if defined(_AIX) && (SIZEOF_LONG == 8) + long clk_id; + if (!PyArg_ParseTuple(args, "l:clock_gettime", &clk_id)) { + #else + int clk_id; + if (!PyArg_ParseTuple(args, "i:clock_gettime", &clk_id)) { + #endif + return NULL; + } - ret = clock_gettime((clockid_t)clk_id, &tp); - if (ret != 0) { - PyErr_SetFromErrno(PyExc_OSError); + ret = clock_gettime((clockid_t)clk_id, &tp); + if (ret != 0) { + PyErr_SetFromErrno(PyExc_OSError); + return NULL; + } + return PyFloat_FromDouble(tp.tv_sec + tp.tv_nsec * 1e-9); + } else { + PyErr_SetString(PyExc_NotImplementedError, "clock_gettime is not available"); return NULL; } - return PyFloat_FromDouble(tp.tv_sec + tp.tv_nsec * 1e-9); } PyDoc_STRVAR(clock_gettime_doc, @@ -181,24 +200,29 @@ Return the time of the specified clock clk_id."); static PyObject * time_clock_gettime_ns(PyObject *self, PyObject *args) { - int ret; - int clk_id; - struct timespec ts; - _PyTime_t t; + if (HAVE_CLOCK_GETTIME_RUNTIME) { + int ret; + int clk_id; + struct timespec ts; + _PyTime_t t; - if (!PyArg_ParseTuple(args, "i:clock_gettime", &clk_id)) { - return NULL; - } + if (!PyArg_ParseTuple(args, "i:clock_gettime", &clk_id)) { + return NULL; + } - ret = clock_gettime((clockid_t)clk_id, &ts); - if (ret != 0) { - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - if (_PyTime_FromTimespec(&t, &ts) < 0) { + ret = clock_gettime((clockid_t)clk_id, &ts); + if (ret != 0) { + PyErr_SetFromErrno(PyExc_OSError); + return NULL; + } + if (_PyTime_FromTimespec(&t, &ts) < 0) { + return NULL; + } + return _PyTime_AsNanosecondsObject(t); + } else { + PyErr_SetString(PyExc_NotImplementedError, "clock_gettime is not available"); return NULL; } - return _PyTime_AsNanosecondsObject(t); } PyDoc_STRVAR(clock_gettime_ns_doc, @@ -211,27 +235,32 @@ Return the time of the specified clock clk_id as nanoseconds."); static PyObject * time_clock_settime(PyObject *self, PyObject *args) { - int clk_id; - PyObject *obj; - _PyTime_t t; - struct timespec tp; - int ret; - - if (!PyArg_ParseTuple(args, "iO:clock_settime", &clk_id, &obj)) - return NULL; + if (HAVE_CLOCK_SETTIME_RUNTIME) { + int clk_id; + PyObject *obj; + _PyTime_t t; + struct timespec tp; + int ret; + + if (!PyArg_ParseTuple(args, "iO:clock_settime", &clk_id, &obj)) + return NULL; - if (_PyTime_FromSecondsObject(&t, obj, _PyTime_ROUND_FLOOR) < 0) - return NULL; + if (_PyTime_FromSecondsObject(&t, obj, _PyTime_ROUND_FLOOR) < 0) + return NULL; - if (_PyTime_AsTimespec(t, &tp) == -1) - return NULL; + if (_PyTime_AsTimespec(t, &tp) == -1) + return NULL; - ret = clock_settime((clockid_t)clk_id, &tp); - if (ret != 0) { - PyErr_SetFromErrno(PyExc_OSError); + ret = clock_settime((clockid_t)clk_id, &tp); + if (ret != 0) { + PyErr_SetFromErrno(PyExc_OSError); + return NULL; + } + Py_RETURN_NONE; + } else { + PyErr_SetString(PyExc_NotImplementedError, "clock_settime is not available"); return NULL; } - Py_RETURN_NONE; } PyDoc_STRVAR(clock_settime_doc, @@ -242,29 +271,34 @@ Set the time of the specified clock clk_id."); static PyObject * time_clock_settime_ns(PyObject *self, PyObject *args) { - int clk_id; - PyObject *obj; - _PyTime_t t; - struct timespec ts; - int ret; - - if (!PyArg_ParseTuple(args, "iO:clock_settime", &clk_id, &obj)) { - return NULL; - } + if (HAVE_CLOCK_SETTIME_RUNTIME) { + int clk_id; + PyObject *obj; + _PyTime_t t; + struct timespec ts; + int ret; + + if (!PyArg_ParseTuple(args, "iO:clock_settime", &clk_id, &obj)) { + return NULL; + } - if (_PyTime_FromNanosecondsObject(&t, obj) < 0) { - return NULL; - } - if (_PyTime_AsTimespec(t, &ts) == -1) { - return NULL; - } + if (_PyTime_FromNanosecondsObject(&t, obj) < 0) { + return NULL; + } + if (_PyTime_AsTimespec(t, &ts) == -1) { + return NULL; + } - ret = clock_settime((clockid_t)clk_id, &ts); - if (ret != 0) { - PyErr_SetFromErrno(PyExc_OSError); + ret = clock_settime((clockid_t)clk_id, &ts); + if (ret != 0) { + PyErr_SetFromErrno(PyExc_OSError); + return NULL; + } + Py_RETURN_NONE; + } else { + PyErr_SetString(PyExc_NotImplementedError, "clock_settime is not available"); return NULL; } - Py_RETURN_NONE; } PyDoc_STRVAR(clock_settime_ns_doc, @@ -277,20 +311,25 @@ Set the time of the specified clock clk_id with nanoseconds."); static PyObject * time_clock_getres(PyObject *self, PyObject *args) { - int ret; - int clk_id; - struct timespec tp; + if (HAVE_CLOCK_GETRES_RUNTIME) { + int ret; + int clk_id; + struct timespec tp; - if (!PyArg_ParseTuple(args, "i:clock_getres", &clk_id)) - return NULL; + if (!PyArg_ParseTuple(args, "i:clock_getres", &clk_id)) + return NULL; - ret = clock_getres((clockid_t)clk_id, &tp); - if (ret != 0) { - PyErr_SetFromErrno(PyExc_OSError); + ret = clock_getres((clockid_t)clk_id, &tp); + if (ret != 0) { + PyErr_SetFromErrno(PyExc_OSError); + return NULL; + } + + return PyFloat_FromDouble(tp.tv_sec + tp.tv_nsec * 1e-9); + } else { + PyErr_SetString(PyExc_NotImplementedError, "clock_getres is not available"); return NULL; } - - return PyFloat_FromDouble(tp.tv_sec + tp.tv_nsec * 1e-9); } PyDoc_STRVAR(clock_getres_doc, @@ -1170,23 +1209,25 @@ _PyTime_GetProcessTimeWithInfo(_PyTime_t *tp, _Py_clock_info_t *info) const char *function = "clock_gettime(CLOCK_PROCESS_CPUTIME_ID)"; #endif - if (clock_gettime(clk_id, &ts) == 0) { - if (info) { - struct timespec res; - info->implementation = function; - info->monotonic = 1; - info->adjustable = 0; - if (clock_getres(clk_id, &res)) { - PyErr_SetFromErrno(PyExc_OSError); - return -1; + if (HAVE_CLOCK_GETTIME_RUNTIME) { + if (clock_gettime(clk_id, &ts) == 0) { + if (info) { + struct timespec res; + info->implementation = function; + info->monotonic = 1; + info->adjustable = 0; + if (clock_getres(clk_id, &res)) { + PyErr_SetFromErrno(PyExc_OSError); + return -1; + } + info->resolution = res.tv_sec + res.tv_nsec * 1e-9; } - info->resolution = res.tv_sec + res.tv_nsec * 1e-9; - } - if (_PyTime_FromTimespec(tp, &ts) < 0) { - return -1; + if (_PyTime_FromTimespec(tp, &ts) < 0) { + return -1; + } + return 0; } - return 0; } #endif @@ -1309,6 +1350,7 @@ sum of the kernel and user-space CPU time."); #if defined(MS_WINDOWS) #define HAVE_THREAD_TIME +#define HAVE_THREAD_TIME_RUNTIME 1 static int _PyTime_GetThreadTimeWithInfo(_PyTime_t *tp, _Py_clock_info_t *info) { @@ -1349,6 +1391,7 @@ _PyTime_GetThreadTimeWithInfo(_PyTime_t *tp, _Py_clock_info_t *info) #elif defined(_AIX) #define HAVE_THREAD_TIME +#define HAVE_THREAD_TIME_RUNTIME 1 static int _PyTime_GetThreadTimeWithInfo(_PyTime_t *tp, _Py_clock_info_t *info) { @@ -1373,6 +1416,7 @@ _PyTime_GetThreadTimeWithInfo(_PyTime_t *tp, _Py_clock_info_t *info) #elif defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_PROCESS_CPUTIME_ID) #define HAVE_THREAD_TIME +#define HAVE_THREAD_TIME_RUNTIME HAVE_CLOCK_GETTIME_RUNTIME static int _PyTime_GetThreadTimeWithInfo(_PyTime_t *tp, _Py_clock_info_t *info) { @@ -1380,10 +1424,16 @@ _PyTime_GetThreadTimeWithInfo(_PyTime_t *tp, _Py_clock_info_t *info) const clockid_t clk_id = CLOCK_THREAD_CPUTIME_ID; const char *function = "clock_gettime(CLOCK_THREAD_CPUTIME_ID)"; - if (clock_gettime(clk_id, &ts)) { - PyErr_SetFromErrno(PyExc_OSError); + if (HAVE_CLOCK_GETTIME_RUNTIME) { + if (clock_gettime(clk_id, &ts)) { + PyErr_SetFromErrno(PyExc_OSError); + return -1; + } + } else { + PyErr_SetString(PyExc_NotImplementedError, "clock_gettime is not available"); return -1; } + if (info) { struct timespec res; info->implementation = function; @@ -1694,17 +1744,6 @@ init_timezone(PyObject *m) static PyMethodDef time_methods[] = { {"time", time_time, METH_NOARGS, time_doc}, {"time_ns", time_time_ns, METH_NOARGS, time_ns_doc}, -#ifdef HAVE_CLOCK_GETTIME - {"clock_gettime", time_clock_gettime, METH_VARARGS, clock_gettime_doc}, - {"clock_gettime_ns",time_clock_gettime_ns, METH_VARARGS, clock_gettime_ns_doc}, -#endif -#ifdef HAVE_CLOCK_SETTIME - {"clock_settime", time_clock_settime, METH_VARARGS, clock_settime_doc}, - {"clock_settime_ns",time_clock_settime_ns, METH_VARARGS, clock_settime_ns_doc}, -#endif -#ifdef HAVE_CLOCK_GETRES - {"clock_getres", time_clock_getres, METH_VARARGS, clock_getres_doc}, -#endif #ifdef HAVE_PTHREAD_GETCPUCLOCKID {"pthread_getcpuclockid", time_pthread_getcpuclockid, METH_VARARGS, pthread_getcpuclockid_doc}, #endif @@ -1727,13 +1766,24 @@ static PyMethodDef time_methods[] = { {"monotonic_ns", time_monotonic_ns, METH_NOARGS, monotonic_ns_doc}, {"process_time", time_process_time, METH_NOARGS, process_time_doc}, {"process_time_ns", time_process_time_ns, METH_NOARGS, process_time_ns_doc}, + {"perf_counter", time_perf_counter, METH_NOARGS, perf_counter_doc}, + {"perf_counter_ns", time_perf_counter_ns, METH_NOARGS, perf_counter_ns_doc}, + {"get_clock_info", time_get_clock_info, METH_VARARGS, get_clock_info_doc}, +#ifdef HAVE_CLOCK_GETTIME + {"clock_gettime", time_clock_gettime, METH_VARARGS, clock_gettime_doc}, + {"clock_gettime_ns",time_clock_gettime_ns, METH_VARARGS, clock_gettime_ns_doc}, +#endif +#ifdef HAVE_CLOCK_SETTIME + {"clock_settime", time_clock_settime, METH_VARARGS, clock_settime_doc}, + {"clock_settime_ns",time_clock_settime_ns, METH_VARARGS, clock_settime_ns_doc}, +#endif #ifdef HAVE_THREAD_TIME {"thread_time", time_thread_time, METH_NOARGS, thread_time_doc}, {"thread_time_ns", time_thread_time_ns, METH_NOARGS, thread_time_ns_doc}, #endif - {"perf_counter", time_perf_counter, METH_NOARGS, perf_counter_doc}, - {"perf_counter_ns", time_perf_counter_ns, METH_NOARGS, perf_counter_ns_doc}, - {"get_clock_info", time_get_clock_info, METH_VARARGS, get_clock_info_doc}, +#ifdef HAVE_CLOCK_GETRES + {"clock_getres", time_clock_getres, METH_VARARGS, clock_getres_doc}, +#endif {NULL, NULL} /* sentinel */ }; @@ -1874,9 +1924,49 @@ static struct PyModuleDef timemodule = { NULL }; +static void +delete_method(const char *name) +{ + for (int i = 0; time_methods[i].ml_name != NULL; i++) { + if ( 0==strcmp(time_methods[i].ml_name, name)) { + for (int j = i; time_methods[j].ml_name != NULL; j++) { + time_methods[j] = time_methods[j+1]; + } + break; + } + } +} + PyMODINIT_FUNC PyInit_time(void) { + #ifdef HAVE_CLOCK_GETTIME + if (HAVE_CLOCK_GETTIME_RUNTIME) {} else { + delete_method("clock_gettime"); + delete_method("clock_gettime_ns"); + } + #endif + + #ifdef HAVE_CLOCK_SETTIME + if (HAVE_CLOCK_SETTIME_RUNTIME) {} else { + delete_method("clock_settime"); + delete_method("clock_settime_ns"); + } + #endif + + #ifdef HAVE_CLOCK_GETRES + if (HAVE_CLOCK_GETRES_RUNTIME) {} else { + delete_method("clock_getres"); + } + #endif + + #ifdef HAVE_THREAD_TIME + if (HAVE_THREAD_TIME_RUNTIME) {} else { + delete_method("thread_time"); + delete_method("thread_time_ns"); + } + #endif + return PyModuleDef_Init(&timemodule); } diff --git a/Python/bootstrap_hash.c b/Python/bootstrap_hash.c index 47369305ee88e9..0dc86e2cf9f5f4 100644 --- a/Python/bootstrap_hash.c +++ b/Python/bootstrap_hash.c @@ -31,6 +31,16 @@ int _Py_HashSecret_Initialized = 0; static int _Py_HashSecret_Initialized = 0; #endif +#if defined(__APPLE__) +#include +#endif + +#if defined(__APPLE__) && HAVE_BUILTIN_AVAILABLE && !(TARGET_OS_OSX && __arm64__) +#define HAVE_GETENTROPY_RUNTIME __builtin_available(macos 10.12, ios 10, tvos 10, watchos 3, *) +#else +#define HAVE_GETENTROPY_RUNTIME 1 +#endif + #ifdef MS_WINDOWS static HCRYPTPROV hCryptProv = 0; @@ -225,13 +235,19 @@ py_getentropy(char *buffer, Py_ssize_t size, int raise) Py_ssize_t len = Py_MIN(size, 256); int res; - if (raise) { - Py_BEGIN_ALLOW_THREADS - res = getentropy(buffer, len); - Py_END_ALLOW_THREADS - } - else { - res = getentropy(buffer, len); + + if (HAVE_GETENTROPY_RUNTIME) { + if (raise) { + Py_BEGIN_ALLOW_THREADS + res = getentropy(buffer, len); + Py_END_ALLOW_THREADS + } + else { + res = getentropy(buffer, len); + } + } else { + getentropy_works = 0; + return 0; } if (res < 0) { diff --git a/Python/pytime.c b/Python/pytime.c index b121b432f428d7..9757e5abc8e8a1 100644 --- a/Python/pytime.c +++ b/Python/pytime.c @@ -7,6 +7,12 @@ #include /* mach_absolute_time(), mach_timebase_info() */ #endif +#if defined(__APPLE__) && HAVE_BUILTIN_AVAILABLE && !defined(__arm64__) +#define HAVE_CLOCK_GETTIME_RUNTIME __builtin_available(macos 10.12, ios 10, tvos 10, watchos 3, *) +#else +#define HAVE_CLOCK_GETTIME_RUNTIME 1 +#endif + #define _PyTime_check_mul_overflow(a, b) \ (assert(b > 0), \ (_PyTime_t)(a) < _PyTime_MIN / (_PyTime_t)(b) \ @@ -683,59 +689,58 @@ pygettimeofday(_PyTime_t *tp, _Py_clock_info_t *info, int raise) #else /* MS_WINDOWS */ int err; -#ifdef HAVE_CLOCK_GETTIME - struct timespec ts; -#else - struct timeval tv; -#endif assert(info == NULL || raise); #ifdef HAVE_CLOCK_GETTIME - err = clock_gettime(CLOCK_REALTIME, &ts); - if (err) { - if (raise) { - PyErr_SetFromErrno(PyExc_OSError); + if (HAVE_CLOCK_GETTIME_RUNTIME) { + struct timespec ts; + err = clock_gettime(CLOCK_REALTIME, &ts); + if (err) { + if (raise) { + PyErr_SetFromErrno(PyExc_OSError); + } + return -1; + } + if (pytime_fromtimespec(tp, &ts, raise) < 0) { + return -1; } - return -1; - } - if (pytime_fromtimespec(tp, &ts, raise) < 0) { - return -1; - } - if (info) { - struct timespec res; - info->implementation = "clock_gettime(CLOCK_REALTIME)"; - info->monotonic = 0; - info->adjustable = 1; - if (clock_getres(CLOCK_REALTIME, &res) == 0) { - info->resolution = res.tv_sec + res.tv_nsec * 1e-9; + if (info) { + struct timespec res; + info->implementation = "clock_gettime(CLOCK_REALTIME)"; + info->monotonic = 0; + info->adjustable = 1; + if (clock_getres(CLOCK_REALTIME, &res) == 0) { + info->resolution = res.tv_sec + res.tv_nsec * 1e-9; + } + else { + info->resolution = 1e-9; + } } - else { - info->resolution = 1e-9; + } else +#endif /* HAVE_CLOCK_GETTIME */ + { + struct timeval tv; + /* test gettimeofday() */ + err = gettimeofday(&tv, (struct timezone *)NULL); + if (err) { + if (raise) { + PyErr_SetFromErrno(PyExc_OSError); + } + return -1; } - } -#else /* HAVE_CLOCK_GETTIME */ - - /* test gettimeofday() */ - err = gettimeofday(&tv, (struct timezone *)NULL); - if (err) { - if (raise) { - PyErr_SetFromErrno(PyExc_OSError); + if (pytime_fromtimeval(tp, &tv, raise) < 0) { + return -1; } - return -1; - } - if (pytime_fromtimeval(tp, &tv, raise) < 0) { - return -1; - } - if (info) { - info->implementation = "gettimeofday()"; - info->resolution = 1e-6; - info->monotonic = 0; - info->adjustable = 1; + if (info) { + info->implementation = "gettimeofday()"; + info->resolution = 1e-6; + info->monotonic = 0; + info->adjustable = 1; + } } -#endif /* !HAVE_CLOCK_GETTIME */ #endif /* !MS_WINDOWS */ return 0; } diff --git a/configure b/configure index 5024860ca4395a..ebdd1cfeed261d 100755 --- a/configure +++ b/configure @@ -12190,6 +12190,41 @@ $as_echo "yes" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking to see if the compiler supports __builtin_available" >&5 +$as_echo_n "checking to see if the compiler supports __builtin_available... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + +int +main () +{ + + if (__builtin_available(macOS 10.8, iOS 5.0, *)) {} + + ; + return 0; +} + +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +cat >>confdefs.h <<_ACEOF +#define HAVE_BUILTIN_AVAILABLE 1 +_ACEOF + + +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + for ac_prog in true do # Extract the first word of "$ac_prog", so it can be a program name with args. diff --git a/configure.ac b/configure.ac index 5a3e340aa3e72b..6df35971dec8d3 100644 --- a/configure.ac +++ b/configure.ac @@ -3825,6 +3825,19 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ AC_MSG_RESULT(yes) ]) +AC_MSG_CHECKING([to see if the compiler supports __builtin_available]) +AC_COMPILE_IFELSE([ + AC_LANG_PROGRAM([[]],[[ + if (__builtin_available(macOS 10.8, iOS 5.0, *)) {} + ]]) + ],[ + AC_MSG_RESULT([yes]) + AC_DEFINE_UNQUOTED(HAVE_BUILTIN_AVAILABLE, 1, + [Define to 1 if the compiler supports __builtin_available]) + ],[ + AC_MSG_RESULT([no]) +]) + dnl check for true AC_CHECK_PROGS(TRUE, true, /bin/true) diff --git a/pyconfig.h.in b/pyconfig.h.in index bc906a869b623e..e602a4a9f4bdc1 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -115,6 +115,9 @@ /* Define if `unsetenv` does not return an int. */ #undef HAVE_BROKEN_UNSETENV +#undef HAVE_BUILTIN_AVAILABLE +/* Define to 1 if the compiler supports __builtin_available */ + /* Has builtin atomics */ #undef HAVE_BUILTIN_ATOMIC From a097234c3bdac3ae2362aa06913280107047329b Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Tue, 21 Jul 2020 02:29:19 +0000 Subject: [PATCH 2/2] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20blu?= =?UTF-8?q?rb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Misc/NEWS.d/next/macOS/2020-07-21-02-29-17.bpo-41100.kFtqID.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/macOS/2020-07-21-02-29-17.bpo-41100.kFtqID.rst diff --git a/Misc/NEWS.d/next/macOS/2020-07-21-02-29-17.bpo-41100.kFtqID.rst b/Misc/NEWS.d/next/macOS/2020-07-21-02-29-17.bpo-41100.kFtqID.rst new file mode 100644 index 00000000000000..ce0eb59a16f8d8 --- /dev/null +++ b/Misc/NEWS.d/next/macOS/2020-07-21-02-29-17.bpo-41100.kFtqID.rst @@ -0,0 +1 @@ +Add runtime checks for MACOSX_DEPLOYMENT_TARGET=10.10 so backwards compatible python can be built with latest Xcode \ No newline at end of file