[Python-checkins] cpython: Issue #22043: _PyTime_Init() now checks if the system clock works.

victor.stinner python-checkins at python.org
Fri Aug 29 16:48:14 CEST 2014


http://hg.python.org/cpython/rev/668e0bf30042
changeset:   92265:668e0bf30042
user:        Victor Stinner <victor.stinner at gmail.com>
date:        Fri Aug 29 16:31:59 2014 +0200
summary:
  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.

files:
  Include/pytime.h     |   13 +-
  Modules/timemodule.c |    5 +-
  Python/pythonrun.c   |    3 +-
  Python/pytime.c      |  145 ++++++++++++------------------
  4 files changed, 73 insertions(+), 93 deletions(-)


diff --git a/Include/pytime.h b/Include/pytime.h
--- a/Include/pytime.h
+++ b/Include/pytime.h
@@ -13,6 +13,8 @@
 extern "C" {
 #endif
 
+#ifndef Py_LIMITED_API
+
 #ifdef HAVE_GETTIMEOFDAY
 typedef struct timeval _PyTime_timeval;
 #else
@@ -37,7 +39,7 @@
 
 /* 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 @@
     ((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 @@
     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
--- a/Modules/timemodule.c
+++ b/Modules/timemodule.c
@@ -1535,7 +1535,10 @@
 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
--- a/Python/pythonrun.c
+++ b/Python/pythonrun.c
@@ -452,7 +452,8 @@
     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
--- 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 @@
     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 @@
 #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->implementation = "gettimeofday()";
+        info->resolution = 1e-6;
         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->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 @@
     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;
 }

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list