]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-110850: Fix _PyTime_FromSecondsDouble() API (#116606)
authorVictor Stinner <vstinner@python.org>
Mon, 11 Mar 2024 16:35:29 +0000 (17:35 +0100)
committerGitHub <noreply@github.com>
Mon, 11 Mar 2024 16:35:29 +0000 (16:35 +0000)
Return 0 on success. Set an exception and return -1 on error.

Fix os.timerfd_settime(): properly report exceptions on
_PyTime_FromSecondsDouble() failure.

No longer export _PyTime_FromSecondsDouble().

Include/internal/pycore_time.h
Modules/clinic/posixmodule.c.h
Modules/posixmodule.c
Python/pytime.c

index 40b28e0ba221aeec6289e806ea1e39ab44d577ec..138d60fdb6980694884b8f3ca0b3f19b79041745 100644 (file)
@@ -132,8 +132,10 @@ PyAPI_FUNC(int) _PyTime_ObjectToTimespec(
 PyAPI_FUNC(PyTime_t) _PyTime_FromSeconds(int seconds);
 
 // Create a timestamp from a number of seconds in double.
-// Export for '_socket' shared extension.
-PyAPI_FUNC(PyTime_t) _PyTime_FromSecondsDouble(double seconds, _PyTime_round_t round);
+extern int _PyTime_FromSecondsDouble(
+    double seconds,
+    _PyTime_round_t round,
+    PyTime_t *result);
 
 // Macro to create a timestamp from a number of seconds, no integer overflow.
 // Only use the macro for small values, prefer _PyTime_FromSeconds().
index b49d64d4281889ec37f095c6e084efffd22d415e..b7338d138e91ce9be7431981a9f9df046de90892 100644 (file)
@@ -6279,8 +6279,8 @@ PyDoc_STRVAR(os_timerfd_settime__doc__,
     {"timerfd_settime", _PyCFunction_CAST(os_timerfd_settime), METH_FASTCALL|METH_KEYWORDS, os_timerfd_settime__doc__},
 
 static PyObject *
-os_timerfd_settime_impl(PyObject *module, int fd, int flags, double initial,
-                        double interval);
+os_timerfd_settime_impl(PyObject *module, int fd, int flags,
+                        double initial_double, double interval_double);
 
 static PyObject *
 os_timerfd_settime(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
@@ -6315,8 +6315,8 @@ os_timerfd_settime(PyObject *module, PyObject *const *args, Py_ssize_t nargs, Py
     Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1;
     int fd;
     int flags = 0;
-    double initial = 0.0;
-    double interval = 0.0;
+    double initial_double = 0.0;
+    double interval_double = 0.0;
 
     args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf);
     if (!args) {
@@ -6339,12 +6339,12 @@ os_timerfd_settime(PyObject *module, PyObject *const *args, Py_ssize_t nargs, Py
     }
     if (args[2]) {
         if (PyFloat_CheckExact(args[2])) {
-            initial = PyFloat_AS_DOUBLE(args[2]);
+            initial_double = PyFloat_AS_DOUBLE(args[2]);
         }
         else
         {
-            initial = PyFloat_AsDouble(args[2]);
-            if (initial == -1.0 && PyErr_Occurred()) {
+            initial_double = PyFloat_AsDouble(args[2]);
+            if (initial_double == -1.0 && PyErr_Occurred()) {
                 goto exit;
             }
         }
@@ -6353,17 +6353,17 @@ os_timerfd_settime(PyObject *module, PyObject *const *args, Py_ssize_t nargs, Py
         }
     }
     if (PyFloat_CheckExact(args[3])) {
-        interval = PyFloat_AS_DOUBLE(args[3]);
+        interval_double = PyFloat_AS_DOUBLE(args[3]);
     }
     else
     {
-        interval = PyFloat_AsDouble(args[3]);
-        if (interval == -1.0 && PyErr_Occurred()) {
+        interval_double = PyFloat_AsDouble(args[3]);
+        if (interval_double == -1.0 && PyErr_Occurred()) {
             goto exit;
         }
     }
 skip_optional_kwonly:
-    return_value = os_timerfd_settime_impl(module, fd, flags, initial, interval);
+    return_value = os_timerfd_settime_impl(module, fd, flags, initial_double, interval_double);
 
 exit:
     return return_value;
@@ -12588,4 +12588,4 @@ os__supports_virtual_terminal(PyObject *module, PyObject *Py_UNUSED(ignored))
 #ifndef OS__SUPPORTS_VIRTUAL_TERMINAL_METHODDEF
     #define OS__SUPPORTS_VIRTUAL_TERMINAL_METHODDEF
 #endif /* !defined(OS__SUPPORTS_VIRTUAL_TERMINAL_METHODDEF) */
-/*[clinic end generated code: output=268af5cbc8baa9d4 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=2965306970f31c5d input=a9049054013a1b77]*/
index 940a9cc8955e1104666198e5222361f75f7fe5e9..f3403e1675276ba8ab79d312c3c3320d7f0ce9a3 100644 (file)
@@ -10483,30 +10483,40 @@ os.timerfd_settime
     *
     flags: int = 0
         0 or a bit mask of TFD_TIMER_ABSTIME or TFD_TIMER_CANCEL_ON_SET.
-    initial: double = 0.0
+    initial as initial_double: double = 0.0
         The initial expiration time, in seconds.
-    interval: double = 0.0
+    interval as interval_double: double = 0.0
         The timer's interval, in seconds.
 
 Alter a timer file descriptor's internal timer in seconds.
 [clinic start generated code]*/
 
 static PyObject *
-os_timerfd_settime_impl(PyObject *module, int fd, int flags, double initial,
-                        double interval)
-/*[clinic end generated code: output=0dda31115317adb9 input=6c24e47e7a4d799e]*/
+os_timerfd_settime_impl(PyObject *module, int fd, int flags,
+                        double initial_double, double interval_double)
+/*[clinic end generated code: output=df4c1bce6859224e input=81d2c0d7e936e8a7]*/
 {
-    struct itimerspec new_value;
-    struct itimerspec old_value;
-    int result;
-    if (_PyTime_AsTimespec(_PyTime_FromSecondsDouble(initial, _PyTime_ROUND_FLOOR), &new_value.it_value) < 0) {
+    PyTime_t initial, interval;
+    if (_PyTime_FromSecondsDouble(initial_double, _PyTime_ROUND_FLOOR,
+                                  &initial) < 0) {
+        return NULL;
+    }
+    if (_PyTime_FromSecondsDouble(interval_double, _PyTime_ROUND_FLOOR,
+                                  &interval) < 0) {
+        return NULL;
+    }
+
+    struct itimerspec new_value, old_value;
+    if (_PyTime_AsTimespec(initial, &new_value.it_value) < 0) {
         PyErr_SetString(PyExc_ValueError, "invalid initial value");
         return NULL;
     }
-    if (_PyTime_AsTimespec(_PyTime_FromSecondsDouble(interval, _PyTime_ROUND_FLOOR), &new_value.it_interval) < 0) {
+    if (_PyTime_AsTimespec(interval, &new_value.it_interval) < 0) {
         PyErr_SetString(PyExc_ValueError, "invalid interval value");
         return NULL;
     }
+
+    int result;
     Py_BEGIN_ALLOW_THREADS
     result = timerfd_settime(fd, flags, &new_value, &old_value);
     Py_END_ALLOW_THREADS
index 90ef2eeb546f7fdea01edb2e80010e2f275459e8..70d92ca00ee28e3f72e825c9490fc3dcb88bca80 100644 (file)
@@ -565,6 +565,7 @@ pytime_from_double(PyTime_t *tp, double value, _PyTime_round_t round,
     /* See comments in pytime_double_to_denominator */
     if (!((double)PyTime_MIN <= d && d < -(double)PyTime_MIN)) {
         pytime_time_t_overflow();
+        *tp = 0;
         return -1;
     }
     PyTime_t ns = (PyTime_t)d;
@@ -652,14 +653,10 @@ _PyTime_AsLong(PyTime_t ns)
     return PyLong_FromLongLong((long long)ns);
 }
 
-PyTime_t
-_PyTime_FromSecondsDouble(double seconds, _PyTime_round_t round)
+int
+_PyTime_FromSecondsDouble(double seconds, _PyTime_round_t round, PyTime_t *result)
 {
-    PyTime_t tp;
-    if(pytime_from_double(&tp, seconds, round, SEC_TO_NS) < 0) {
-        return -1;
-    }
-    return tp;
+    return pytime_from_double(result, seconds, round, SEC_TO_NS);
 }