summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVictor Stinner <victor.stinner@gmail.com>2014-08-29 14:31:59 (GMT)
committerVictor Stinner <victor.stinner@gmail.com>2014-08-29 14:31:59 (GMT)
commit0011124dc235fb9af1a80acf3df7edd8816c0a9d (patch)
treeb4c63644aa1fecc1a3ad188da1a73a9f2812c380
parent7efb83393cbe08924682c6852e94d3c4a4033c34 (diff)
downloadcpython-0011124dc235fb9af1a80acf3df7edd8816c0a9d.zip
cpython-0011124dc235fb9af1a80acf3df7edd8816c0a9d.tar.gz
cpython-0011124dc235fb9af1a80acf3df7edd8816c0a9d.tar.bz2
Issue #22043: _PyTime_Init() now checks if the system clock works.
Other changes: * The whole _PyTime API is private (not defined if Py_LIMITED_API is set) * _PyTime_gettimeofday_info() also returns -1 on error * Simplify PyTime_gettimeofday(): only use clock_gettime(CLOCK_REALTIME) or gettimeofday() on UNIX. Don't fallback to ftime() or time() anymore.
-rw-r--r--Include/pytime.h13
-rw-r--r--Modules/timemodule.c5
-rw-r--r--Python/pythonrun.c3
-rw-r--r--Python/pytime.c145
4 files changed, 73 insertions, 93 deletions
diff --git a/Include/pytime.h b/Include/pytime.h
index b0fc6d0..14e9596 100644
--- a/Include/pytime.h
+++ b/Include/pytime.h
@@ -13,6 +13,8 @@ functions and constants
extern "C" {
#endif
+#ifndef Py_LIMITED_API
+
#ifdef HAVE_GETTIMEOFDAY
typedef struct timeval _PyTime_timeval;
#else
@@ -37,7 +39,7 @@ PyAPI_FUNC(void) _PyTime_gettimeofday(_PyTime_timeval *tp);
/* Similar to _PyTime_gettimeofday() but retrieve also information on the
* clock used to get the current time. */
-PyAPI_FUNC(void) _PyTime_gettimeofday_info(
+PyAPI_FUNC(int) _PyTime_gettimeofday_info(
_PyTime_timeval *tp,
_Py_clock_info_t *info);
@@ -52,8 +54,6 @@ do { \
((tv_end.tv_sec - tv_start.tv_sec) + \
(tv_end.tv_usec - tv_start.tv_usec) * 0.000001)
-#ifndef Py_LIMITED_API
-
typedef enum {
/* Round towards zero. */
_PyTime_ROUND_DOWN=0,
@@ -92,10 +92,11 @@ PyAPI_FUNC(int) _PyTime_ObjectToTimespec(
time_t *sec,
long *nsec,
_PyTime_round_t);
-#endif
-/* Dummy to force linking. */
-PyAPI_FUNC(void) _PyTime_Init(void);
+/* Initialize time.
+ Return 0 on success, raise an exception and return -1 on error. */
+PyAPI_FUNC(int) _PyTime_Init(void);
+#endif /* Py_LIMITED_API */
#ifdef __cplusplus
}
diff --git a/Modules/timemodule.c b/Modules/timemodule.c
index 2b2b4bd..1a13fd0e 100644
--- a/Modules/timemodule.c
+++ b/Modules/timemodule.c
@@ -1535,7 +1535,10 @@ static PyObject*
floattime(_Py_clock_info_t *info)
{
_PyTime_timeval t;
- _PyTime_gettimeofday_info(&t, info);
+ if (_PyTime_gettimeofday_info(&t, info) < 0) {
+ assert(info != NULL);
+ return NULL;
+ }
return PyFloat_FromDouble((double)t.tv_sec + t.tv_usec * 1e-6);
}
diff --git a/Python/pythonrun.c b/Python/pythonrun.c
index 63d9eeb..bac39c2 100644
--- a/Python/pythonrun.c
+++ b/Python/pythonrun.c
@@ -452,7 +452,8 @@ _Py_InitializeEx_Private(int install_sigs, int install_importlib)
if (_PyFaulthandler_Init())
Py_FatalError("Py_Initialize: can't initialize faulthandler");
- _PyTime_Init();
+ if (_PyTime_Init() < 0)
+ Py_FatalError("Py_Initialize: can't initialize time");
if (initfsencoding(interp) < 0)
Py_FatalError("Py_Initialize: unable to load the file system codec");
diff --git a/Python/pytime.c b/Python/pytime.c
index 1f3fafb..31c8f66 100644
--- a/Python/pytime.c
+++ b/Python/pytime.c
@@ -3,29 +3,16 @@
#include <windows.h>
#endif
-#if defined(__APPLE__) && defined(HAVE_GETTIMEOFDAY) && defined(HAVE_FTIME)
- /*
- * _PyTime_gettimeofday falls back to ftime when getttimeofday fails because the latter
- * might fail on some platforms. This fallback is unwanted on MacOSX because
- * that makes it impossible to use a binary build on OSX 10.4 on earlier
- * releases of the OS. Therefore claim we don't support ftime.
- */
-# undef HAVE_FTIME
-#endif
-
-#if defined(HAVE_FTIME) && !defined(MS_WINDOWS)
-#include <sys/timeb.h>
-extern int ftime(struct timeb *);
-#endif
-
-static void
-pygettimeofday(_PyTime_timeval *tp, _Py_clock_info_t *info)
+static int
+pygettimeofday(_PyTime_timeval *tp, _Py_clock_info_t *info, int raise)
{
#ifdef MS_WINDOWS
FILETIME system_time;
ULARGE_INTEGER large;
ULONGLONG microseconds;
+ assert(info == NULL || raise);
+
GetSystemTimeAsFileTime(&system_time);
large.u.LowPart = system_time.dwLowDateTime;
large.u.HighPart = system_time.dwHighDateTime;
@@ -37,55 +24,51 @@ pygettimeofday(_PyTime_timeval *tp, _Py_clock_info_t *info)
tp->tv_usec = microseconds % 1000000;
if (info) {
DWORD timeAdjustment, timeIncrement;
- BOOL isTimeAdjustmentDisabled;
+ BOOL isTimeAdjustmentDisabled, ok;
info->implementation = "GetSystemTimeAsFileTime()";
info->monotonic = 0;
- (void) GetSystemTimeAdjustment(&timeAdjustment, &timeIncrement,
- &isTimeAdjustmentDisabled);
+ ok = GetSystemTimeAdjustment(&timeAdjustment, &timeIncrement,
+ &isTimeAdjustmentDisabled);
+ if (!ok) {
+ PyErr_SetFromWindowsErr(0);
+ return -1;
+ }
info->resolution = timeIncrement * 1e-7;
info->adjustable = 1;
}
-#else
- /* There are three ways to get the time:
- (1) gettimeofday() -- resolution in microseconds
- (2) ftime() -- resolution in milliseconds
- (3) time() -- resolution in seconds
- In all cases the return value in a timeval struct.
- Since on some systems (e.g. SCO ODT 3.0) gettimeofday() may
- fail, so we fall back on ftime() or time().
- Note: clock resolution does not imply clock accuracy! */
+ return 0;
-#if (defined(HAVE_CLOCK_GETTIME) || defined(HAVE_GETTIMEOFDAY) \
- || defined(HAVE_FTIME))
+#else /* MS_WINDOWS */
int err;
-#endif
#ifdef HAVE_CLOCK_GETTIME
struct timespec ts;
#endif
-#ifdef HAVE_FTIME
- struct timeb t;
-#endif
- /* test clock_gettime(CLOCK_REALTIME) */
+ assert(info == NULL || raise);
+
#ifdef HAVE_CLOCK_GETTIME
- err = clock_gettime(CLOCK_REALTIME, &ts);
- if (err == 0) {
- 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;
- }
- tp->tv_sec = ts.tv_sec;
- tp->tv_usec = ts.tv_nsec / 1000;
- return;
+ err = clock_gettime(CLOCK_REALTIME, &ts);
+ if (err) {
+ if (raise)
+ PyErr_SetFromErrno(PyExc_OSError);
+ return -1;
}
-#endif
+ tp->tv_sec = ts.tv_sec;
+ tp->tv_usec = ts.tv_nsec / 1000;
+
+ 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;
+ }
+ return 0;
+#else /* HAVE_CLOCK_GETTIME */
/* test gettimeofday() */
#ifdef HAVE_GETTIMEOFDAY
@@ -94,51 +77,39 @@ pygettimeofday(_PyTime_timeval *tp, _Py_clock_info_t *info)
#else
err = gettimeofday(tp, (struct timezone *)NULL);
#endif
- if (err == 0) {
- if (info) {
- info->implementation = "gettimeofday()";
- info->resolution = 1e-6;
- info->monotonic = 0;
- info->adjustable = 1;
- }
- return;
+ if (err) {
+ if (raise)
+ PyErr_SetFromErrno(PyExc_OSError);
+ return -1;
}
-#endif /* HAVE_GETTIMEOFDAY */
-#ifdef HAVE_FTIME
- ftime(&t);
- tp->tv_sec = t.time;
- tp->tv_usec = t.millitm * 1000;
- if (info) {
- info->implementation = "ftime()";
- info->resolution = 1e-3;
- info->monotonic = 0;
- info->adjustable = 1;
- }
-#else /* !HAVE_FTIME */
- tp->tv_sec = time(NULL);
- tp->tv_usec = 0;
if (info) {
- info->implementation = "time()";
- info->resolution = 1.0;
+ info->implementation = "gettimeofday()";
+ info->resolution = 1e-6;
info->monotonic = 0;
info->adjustable = 1;
}
-#endif /* !HAVE_FTIME */
-
-#endif /* MS_WINDOWS */
+ return 0;
+#endif /* HAVE_GETTIMEOFDAY */
+#endif /* !HAVE_CLOCK_GETTIME */
+#endif /* !MS_WINDOWS */
}
void
_PyTime_gettimeofday(_PyTime_timeval *tp)
{
- pygettimeofday(tp, NULL);
+ if (pygettimeofday(tp, NULL, 0) < 0) {
+ /* cannot happen, _PyTime_Init() checks that pygettimeofday() works */
+ assert(0);
+ tp->tv_sec = 0;
+ tp->tv_usec = 0;
+ }
}
-void
+int
_PyTime_gettimeofday_info(_PyTime_timeval *tp, _Py_clock_info_t *info)
{
- pygettimeofday(tp, info);
+ return pygettimeofday(tp, info, 1);
}
static void
@@ -273,8 +244,12 @@ _PyTime_ObjectToTimeval(PyObject *obj, time_t *sec, long *usec,
return _PyTime_ObjectToDenominator(obj, sec, usec, 1e6, round);
}
-void
-_PyTime_Init()
+int
+_PyTime_Init(void)
{
- /* Do nothing. Needed to force linking. */
+ _PyTime_timeval tv;
+ /* ensure that the system clock works */
+ if (_PyTime_gettimeofday_info(&tv, NULL) < 0)
+ return -1;
+ return 0;
}