diff options
author | Victor Stinner <vstinner@python.org> | 2020-11-16 15:08:05 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-11-16 15:08:05 (GMT) |
commit | ae6cd7cfdab0599139002c526953d907696d9eef (patch) | |
tree | fbfcfd94f1f73fa6e38a50dc5112a707e59d4c6b /Modules/timemodule.c | |
parent | 5909a494cd3ba43143b28bd439773ed85a485dfc (diff) | |
download | cpython-ae6cd7cfdab0599139002c526953d907696d9eef.zip cpython-ae6cd7cfdab0599139002c526953d907696d9eef.tar.gz cpython-ae6cd7cfdab0599139002c526953d907696d9eef.tar.bz2 |
bpo-37205: time.time() cannot fail with fatal error (GH-23314)
time.time(), time.perf_counter() and time.monotonic() functions can
no longer fail with a Python fatal error, instead raise a regular
Python exception on failure.
Remove _PyTime_Init(): don't check system, monotonic and perf counter
clocks at startup anymore.
On error, _PyTime_GetSystemClock(), _PyTime_GetMonotonicClock() and
_PyTime_GetPerfCounter() now silently ignore the error and return 0.
They cannot fail with a Python fatal error anymore.
Add py_mach_timebase_info() and win_perf_counter_frequency()
sub-functions.
Diffstat (limited to 'Modules/timemodule.c')
-rw-r--r-- | Modules/timemodule.c | 87 |
1 files changed, 65 insertions, 22 deletions
diff --git a/Modules/timemodule.c b/Modules/timemodule.c index 80eab30..4caacc3 100644 --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -51,7 +51,7 @@ #define _Py_tzname tzname #endif -#if defined(__APPLE__ ) && defined(__has_builtin) +#if defined(__APPLE__ ) && defined(__has_builtin) # if __has_builtin(__builtin_available) # define HAVE_CLOCK_GETTIME_RUNTIME __builtin_available(macOS 10.12, iOS 10.0, tvOS 10.0, watchOS 3.0, *) # endif @@ -74,10 +74,21 @@ _PyFloat_FromPyTime(_PyTime_t t) } +static int +get_system_time(_PyTime_t *t) +{ + // Avoid _PyTime_GetSystemClock() which silently ignores errors. + return _PyTime_GetSystemClockWithInfo(t, NULL); +} + + static PyObject * time_time(PyObject *self, PyObject *unused) { - _PyTime_t t = _PyTime_GetSystemClock(); + _PyTime_t t; + if (get_system_time(&t) < 0) { + return NULL; + } return _PyFloat_FromPyTime(t); } @@ -91,7 +102,10 @@ Fractions of a second may be present if the system clock provides them."); static PyObject * time_time_ns(PyObject *self, PyObject *unused) { - _PyTime_t t = _PyTime_GetSystemClock(); + _PyTime_t t; + if (get_system_time(&t) < 0) { + return NULL; + } return _PyTime_AsNanosecondsObject(t); } @@ -147,20 +161,11 @@ _PyTime_GetClockWithInfo(_PyTime_t *tp, _Py_clock_info_t *info) } #endif /* HAVE_CLOCK */ -static PyObject* -perf_counter(_Py_clock_info_t *info) -{ - _PyTime_t t; - if (_PyTime_GetPerfCounterWithInfo(&t, info) < 0) { - return NULL; - } - return _PyFloat_FromPyTime(t); -} #ifdef HAVE_CLOCK_GETTIME #ifdef __APPLE__ -/* +/* * The clock_* functions will be removed from the module * dict entirely when the C API is not available. */ @@ -1096,10 +1101,22 @@ the local timezone used by methods such as localtime, but this behaviour\n\ should not be relied on."); #endif /* HAVE_WORKING_TZSET */ + +static int +get_monotonic(_PyTime_t *t) +{ + // Avoid _PyTime_GetMonotonicClock() which silently ignores errors. + return _PyTime_GetMonotonicClockWithInfo(t, NULL); +} + + static PyObject * time_monotonic(PyObject *self, PyObject *unused) { - _PyTime_t t = _PyTime_GetMonotonicClock(); + _PyTime_t t; + if (get_monotonic(&t) < 0) { + return NULL; + } return _PyFloat_FromPyTime(t); } @@ -1111,7 +1128,10 @@ Monotonic clock, cannot go backward."); static PyObject * time_monotonic_ns(PyObject *self, PyObject *unused) { - _PyTime_t t = _PyTime_GetMonotonicClock(); + _PyTime_t t; + if (get_monotonic(&t) < 0) { + return NULL; + } return _PyTime_AsNanosecondsObject(t); } @@ -1120,10 +1140,23 @@ PyDoc_STRVAR(monotonic_ns_doc, \n\ Monotonic clock, cannot go backward, as nanoseconds."); + +static int +get_perf_counter(_PyTime_t *t) +{ + // Avoid _PyTime_GetPerfCounter() which silently ignores errors. + return _PyTime_GetPerfCounterWithInfo(t, NULL); +} + + static PyObject * time_perf_counter(PyObject *self, PyObject *unused) { - return perf_counter(NULL); + _PyTime_t t; + if (get_perf_counter(&t) < 0) { + return NULL; + } + return _PyFloat_FromPyTime(t); } PyDoc_STRVAR(perf_counter_doc, @@ -1131,10 +1164,14 @@ PyDoc_STRVAR(perf_counter_doc, \n\ Performance counter for benchmarking."); + static PyObject * time_perf_counter_ns(PyObject *self, PyObject *unused) { - _PyTime_t t = _PyTime_GetPerfCounter(); + _PyTime_t t; + if (get_perf_counter(&t) < 0) { + return NULL; + } return _PyTime_AsNanosecondsObject(t); } @@ -1421,7 +1458,7 @@ _PyTime_GetThreadTimeWithInfo(_PyTime_t *tp, _Py_clock_info_t *info) #if defined(__APPLE__) && defined(__has_attribute) && __has_attribute(availability) static int -_PyTime_GetThreadTimeWithInfo(_PyTime_t *tp, _Py_clock_info_t *info) +_PyTime_GetThreadTimeWithInfo(_PyTime_t *tp, _Py_clock_info_t *info) __attribute__((availability(macos, introduced=10.12))) __attribute__((availability(ios, introduced=10.0))) __attribute__((availability(tvos, introduced=10.0))) @@ -1460,7 +1497,7 @@ _PyTime_GetThreadTimeWithInfo(_PyTime_t *tp, _Py_clock_info_t *info) #ifdef HAVE_THREAD_TIME #ifdef __APPLE__ -/* +/* * The clock_* functions will be removed from the module * dict entirely when the C API is not available. */ @@ -2025,7 +2062,10 @@ pysleep(_PyTime_t secs) HANDLE hInterruptEvent; #endif - deadline = _PyTime_GetMonotonicClock() + secs; + if (get_monotonic(&monotonic) < 0) { + return -1; + } + deadline = monotonic + secs; do { #ifndef MS_WINDOWS @@ -2077,10 +2117,13 @@ pysleep(_PyTime_t secs) if (PyErr_CheckSignals()) return -1; - monotonic = _PyTime_GetMonotonicClock(); + if (get_monotonic(&monotonic) < 0) { + return -1; + } secs = deadline - monotonic; - if (secs < 0) + if (secs < 0) { break; + } /* retry with the recomputed delay */ } while (1); |