diff --git a/Include/pytime.h b/Include/pytime.h --- a/Include/pytime.h +++ b/Include/pytime.h @@ -23,8 +23,10 @@ typedef struct { /* Similar to POSIX gettimeofday but cannot fail. If system gettimeofday * fails or is not available, fall back to lower resolution clocks. + * + * Return 0 on success, or raise an exception and return -1 on error. */ -PyAPI_FUNC(void) _PyTime_gettimeofday(_PyTime_timeval *tp); +PyAPI_FUNC(int) _PyTime_gettimeofday(_PyTime_timeval *tp); #define _PyTime_ADD_SECONDS(tv, interval) \ do { \ diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c --- a/Modules/_datetimemodule.c +++ b/Modules/_datetimemodule.c @@ -4132,7 +4132,8 @@ static PyObject * datetime_best_possible(PyObject *cls, TM_FUNC f, PyObject *tzinfo) { _PyTime_timeval t; - _PyTime_gettimeofday(&t); + if (_PyTime_gettimeofday(&t) == -1) + return NULL; return datetime_from_timet_and_us(cls, f, t.tv_sec, (int)t.tv_usec, tzinfo); } diff --git a/Modules/_randommodule.c b/Modules/_randommodule.c --- a/Modules/_randommodule.c +++ b/Modules/_randommodule.c @@ -223,7 +223,12 @@ random_seed(RandomObject *self, PyObject if (arg == NULL || arg == Py_None) { time_t now; + errno = 0; time(&now); + if (now == (time_t)-1 && errno != 0) { + PyErr_SetFromErrno(PyExc_IOError); + return NULL; + } init_genrand(self, (unsigned long)now); Py_INCREF(Py_None); return Py_None; diff --git a/Modules/_threadmodule.c b/Modules/_threadmodule.c --- a/Modules/_threadmodule.c +++ b/Modules/_threadmodule.c @@ -55,7 +55,8 @@ acquire_timed(PyThread_type_lock lock, P if (microseconds > 0) { - _PyTime_gettimeofday(&endtime); + /* FIXME: handle _PyTime_gettimeofday() failure */ + (void)_PyTime_gettimeofday(&endtime); endtime.tv_sec += microseconds / (1000 * 1000); endtime.tv_usec += microseconds % (1000 * 1000); } @@ -77,7 +78,8 @@ acquire_timed(PyThread_type_lock lock, P /* If we're using a timeout, recompute the timeout after processing * signals, since those can take time. */ if (microseconds > 0) { - _PyTime_gettimeofday(&curtime); + /* FIXME: handle _PyTime_gettimeofday() failure */ + (void)_PyTime_gettimeofday(&curtime); microseconds = ((endtime.tv_sec - curtime.tv_sec) * 1000000 + (endtime.tv_usec - curtime.tv_usec)); diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -770,7 +770,8 @@ internal_select(PySocketSockObject *s, i double interval = s->sock_timeout; \ int has_timeout = s->sock_timeout > 0.0; \ if (has_timeout) { \ - _PyTime_gettimeofday(&now); \ + /* FIXME: handle _PyTime_gettimeofday failure */ \ + (void)_PyTime_gettimeofday(&now); \ deadline = now; \ _PyTime_ADD_SECONDS(deadline, s->sock_timeout); \ } \ @@ -781,7 +782,8 @@ internal_select(PySocketSockObject *s, i if (!has_timeout || \ (!CHECK_ERRNO(EWOULDBLOCK) && !CHECK_ERRNO(EAGAIN))) \ break; \ - _PyTime_gettimeofday(&now); \ + /* FIXME: handle _PyTime_gettimeofday failure */ \ + (void)_PyTime_gettimeofday(&now); \ interval = _PyTime_INTERVAL(now, deadline); \ } \ } \ diff --git a/Modules/timemodule.c b/Modules/timemodule.c --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -42,20 +42,42 @@ /* Forward declarations */ static int floatsleep(double); -static double floattime(void); +static int floattime(double *t); static PyObject * time_time(PyObject *self, PyObject *unused) { double secs; - secs = floattime(); - if (secs == 0.0) { - PyErr_SetFromErrno(PyExc_IOError); + if (floattime(&secs) == -1) return NULL; - } return PyFloat_FromDouble(secs); } +static int +pylocaltime(time_t *timep, struct tm *result) +{ + time_t current_time; + struct tm *local; + + if (timep == NULL) { + errno = 0; + current_time = time(NULL); + if (current_time == (time_t)-1 && errno != 0) { + PyErr_SetFromErrno(PyExc_IOError); + return -1; + } + timep = ¤t_time; + } + local = localtime(timep); + if (local == NULL) { + PyErr_SetString(PyExc_ValueError, "unconvertible time"); + return -1; + } + *result = *local; + return 0; +} + + PyDoc_STRVAR(time_doc, "time() -> floating point number\n\ \n\ @@ -76,16 +98,25 @@ time_clock(PyObject *self, PyObject *unu if (divisor == 0.0) { LARGE_INTEGER freq; QueryPerformanceCounter(&ctrStart); - if (!QueryPerformanceFrequency(&freq) || freq.QuadPart == 0) { + if (!QueryPerformanceFrequency(&freq) || freq.QuadPart == 0) + { /* Unlikely to happen - this works on all intel machines at least! Revert to clock() */ - return PyFloat_FromDouble(((double)clock()) / + clock_t processor_time; + processor_time = clock(); + if (processor_time == (clock_t)-1) { + PyErr_SetString(PyExc_RuntimeError, + "the processor time used is not available " + "or its value cannot be represented"); + return -1; + } + return PyFloat_FromDouble((double)processor_time / CLOCKS_PER_SEC); } divisor = (double)freq.QuadPart; } QueryPerformanceCounter(&now); - diff = (double)(now.QuadPart - ctrStart.QuadPart); + diff = now.QuadPart - ctrStart.QuadPart; return PyFloat_FromDouble(diff / divisor); } @@ -102,11 +133,18 @@ time_clock(PyObject *self, PyObject *unu static PyObject * time_clock(PyObject *self, PyObject *unused) { - return PyFloat_FromDouble(((double)clock()) / CLOCKS_PER_SEC); + clock_t value; + value = clock(); + if (value == (clock_t)-1) { + PyErr_SetString(PyExc_RuntimeError, + "the processor time used is not available " + "or its value cannot be represented"); + return NULL; + } + return PyFloat_FromDouble((double)value / CLOCKS_PER_SEC); } #endif /* HAVE_CLOCK */ - #ifdef HAVE_CLOCK PyDoc_STRVAR(clock_doc, "clock() -> floating point number\n\ @@ -278,8 +316,10 @@ parse_time_double_args(PyObject *args, c if (!PyArg_ParseTuple(args, format, &ot)) return 0; - if (ot == NULL || ot == Py_None) - *pwhen = floattime(); + if (ot == NULL || ot == Py_None) { + if (floattime(pwhen) == -1) + return 0; + } else { double when = PyFloat_AsDouble(ot); if (PyErr_Occurred()) @@ -461,8 +501,8 @@ time_strftime(PyObject *self, PyObject * return NULL; if (tup == NULL) { - time_t tt = time(NULL); - buf = *localtime(&tt); + if (pylocaltime(NULL, &buf) == -1) + return NULL; } else if (!gettmarg(tup, &buf) || !checktm(&buf)) return NULL; @@ -626,8 +666,8 @@ time_asctime(PyObject *self, PyObject *a if (!PyArg_UnpackTuple(args, "asctime", 0, 1, &tup)) return NULL; if (tup == NULL) { - time_t tt = time(NULL); - buf = *localtime(&tt); + if (pylocaltime(NULL, &buf) == -1) + return NULL; } else if (!gettmarg(tup, &buf) || !checktm(&buf)) return NULL; return _asctime(&buf); @@ -644,27 +684,29 @@ static PyObject * time_ctime(PyObject *self, PyObject *args) { PyObject *ot = NULL; - time_t tt; - struct tm *timeptr; + struct tm buf; if (!PyArg_UnpackTuple(args, "ctime", 0, 1, &ot)) return NULL; - if (ot == NULL || ot == Py_None) - tt = time(NULL); + if (ot == NULL || ot == Py_None) { + if (pylocaltime(NULL, &buf) == -1) + return NULL; + + } else { - double dt = PyFloat_AsDouble(ot); + double dt; + time_t tt; + + dt = PyFloat_AsDouble(ot); if (PyErr_Occurred()) return NULL; tt = _PyTime_DoubleToTimet(dt); if (tt == (time_t)-1 && PyErr_Occurred()) return NULL; + if (pylocaltime(&tt, &buf) == -1) + return NULL; } - timeptr = localtime(&tt); - if (timeptr == NULL) { - PyErr_SetString(PyExc_ValueError, "unconvertible time"); - return NULL; - } - return _asctime(timeptr); + return _asctime(&buf); } PyDoc_STRVAR(ctime_doc, @@ -742,7 +784,9 @@ time_wallclock(PyObject *self, PyObject { #if defined(MS_WINDOWS) && !defined(__BORLANDC__) return time_clock(self, NULL); -#elif defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC) +#else + +#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC) static int clk_index = 0; clockid_t clk_ids[] = { #ifdef CLOCK_MONOTONIC_RAW @@ -768,8 +812,7 @@ time_wallclock(PyObject *self, PyObject if (Py_ARRAY_LENGTH(clk_ids) <= clk_index) clk_index = -1; } - return time_time(self, NULL); -#else +#endif /* defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC) */ return time_time(self, NULL); #endif } @@ -1003,12 +1046,14 @@ PyInit_time(void) return m; } -static double -floattime(void) +static int +floattime(double *secs) { _PyTime_timeval t; - _PyTime_gettimeofday(&t); - return (double)t.tv_sec + t.tv_usec*0.000001; + if (_PyTime_gettimeofday(&t) == -1) + return -1; + *secs = (double)t.tv_sec + t.tv_usec*0.000001; + return 0; } diff --git a/Python/pytime.c b/Python/pytime.c --- a/Python/pytime.c +++ b/Python/pytime.c @@ -19,7 +19,7 @@ extern int ftime(struct timeb *); #endif /* MS_WINDOWS */ #endif /* HAVE_FTIME */ -void +int _PyTime_gettimeofday(_PyTime_timeval *tp) { /* There are three ways to get the time: @@ -33,24 +33,36 @@ _PyTime_gettimeofday(_PyTime_timeval *tp #ifdef HAVE_GETTIMEOFDAY #ifdef GETTIMEOFDAY_NO_TZ if (gettimeofday(tp) == 0) - return; + return 0; #else /* !GETTIMEOFDAY_NO_TZ */ if (gettimeofday(tp, (struct timezone *)NULL) == 0) - return; + return 0; #endif /* !GETTIMEOFDAY_NO_TZ */ #endif /* !HAVE_GETTIMEOFDAY */ + #if defined(HAVE_FTIME) { struct timeb t; - ftime(&t); + errno = 0; + if (ftime(&t)) + { + PyErr_SetFromErrno(PyExc_IOError); + return -1; + } tp->tv_sec = t.time; tp->tv_usec = t.millitm * 1000; } #else /* !HAVE_FTIME */ + errno = 0; tp->tv_sec = time(NULL); + if (tp->tv_sec == (time_t)-1 && errno != 0) + { + PyErr_SetFromErrno(PyExc_IOError); + return -1; + } tp->tv_usec = 0; #endif /* !HAVE_FTIME */ - return; + return 0; } void