summaryrefslogtreecommitdiffstats
path: root/Modules/timemodule.c
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@python.org>2020-11-16 15:08:05 (GMT)
committerGitHub <noreply@github.com>2020-11-16 15:08:05 (GMT)
commitae6cd7cfdab0599139002c526953d907696d9eef (patch)
treefbfcfd94f1f73fa6e38a50dc5112a707e59d4c6b /Modules/timemodule.c
parent5909a494cd3ba43143b28bd439773ed85a485dfc (diff)
downloadcpython-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.c87
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);