.. versionchanged:: 3.15
Accepts any real number as *timeout*, not only integer or float.
+ If ``ppoll()`` function is available, *timeout* has a resolution
+ of ``1`` ns (``1e-6`` ms) instead of ``1`` ms.
.. _kqueue-objects:
@cpython_only
def test_poll_c_limits(self):
try:
+ import _testcapi
from _testcapi import USHRT_MAX, INT_MAX, UINT_MAX
+ HAVE_PPOLL = getattr(_testcapi, 'HAVE_PPOLL', False)
except ImportError:
raise unittest.SkipTest("requires _testcapi")
+
pollster = select.poll()
pollster.register(1)
# Issues #15989, #17919
self.assertRaises(OverflowError, pollster.register, 0, USHRT_MAX + 1)
self.assertRaises(OverflowError, pollster.modify, 1, USHRT_MAX + 1)
- self.assertRaises(OverflowError, pollster.poll, INT_MAX + 1)
- self.assertRaises(OverflowError, pollster.poll, UINT_MAX + 1)
+ if HAVE_PPOLL:
+ MS_TO_NS = 1_000_000
+ tmax = _testcapi.INT64_MAX // MS_TO_NS
+ self.assertRaises(OverflowError, pollster.poll, tmax + 1)
+ else:
+ self.assertRaises(OverflowError, pollster.poll, INT_MAX + 1)
+ self.assertRaises(OverflowError, pollster.poll, UINT_MAX + 1)
@threading_helper.reap_threads
def test_threaded_poll(self):
--- /dev/null
+Use ``ppoll()`` if available in :func:`select.poll` to have a timeout
+resolution of 1 nanosecond, instead of a resolution of 1 ms. Patch by Victor
+Stinner.
PyModule_AddObject(m, "INT64_MAX", PyLong_FromInt64(INT64_MAX));
PyModule_AddObject(m, "UINT64_MAX", PyLong_FromUInt64(UINT64_MAX));
+#ifdef HAVE_PPOLL
+ if (PyModule_AddObjectRef(m, "HAVE_PPOLL", Py_True) < 0) {
+ return -1;
+ }
+#endif
+
if (PyModule_AddIntMacro(m, _Py_STACK_GROWS_DOWN)) {
return -1;
}
return return_value;
}
-#if (defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL))
+#if ((defined(HAVE_POLL) || defined(HAVE_PPOLL)) && !defined(HAVE_BROKEN_POLL))
PyDoc_STRVAR(select_poll_register__doc__,
"register($self, fd,\n"
return return_value;
}
-#endif /* (defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL)) */
+#endif /* ((defined(HAVE_POLL) || defined(HAVE_PPOLL)) && !defined(HAVE_BROKEN_POLL)) */
-#if (defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL))
+#if ((defined(HAVE_POLL) || defined(HAVE_PPOLL)) && !defined(HAVE_BROKEN_POLL))
PyDoc_STRVAR(select_poll_modify__doc__,
"modify($self, fd, eventmask, /)\n"
return return_value;
}
-#endif /* (defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL)) */
+#endif /* ((defined(HAVE_POLL) || defined(HAVE_PPOLL)) && !defined(HAVE_BROKEN_POLL)) */
-#if (defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL))
+#if ((defined(HAVE_POLL) || defined(HAVE_PPOLL)) && !defined(HAVE_BROKEN_POLL))
PyDoc_STRVAR(select_poll_unregister__doc__,
"unregister($self, fd, /)\n"
return return_value;
}
-#endif /* (defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL)) */
+#endif /* ((defined(HAVE_POLL) || defined(HAVE_PPOLL)) && !defined(HAVE_BROKEN_POLL)) */
-#if (defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL))
+#if ((defined(HAVE_POLL) || defined(HAVE_PPOLL)) && !defined(HAVE_BROKEN_POLL))
PyDoc_STRVAR(select_poll_poll__doc__,
"poll($self, timeout=None, /)\n"
return return_value;
}
-#endif /* (defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL)) */
+#endif /* ((defined(HAVE_POLL) || defined(HAVE_PPOLL)) && !defined(HAVE_BROKEN_POLL)) */
-#if (defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL)) && defined(HAVE_SYS_DEVPOLL_H)
+#if ((defined(HAVE_POLL) || defined(HAVE_PPOLL)) && !defined(HAVE_BROKEN_POLL)) && defined(HAVE_SYS_DEVPOLL_H)
PyDoc_STRVAR(select_devpoll_register__doc__,
"register($self, fd,\n"
return return_value;
}
-#endif /* (defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL)) && defined(HAVE_SYS_DEVPOLL_H) */
+#endif /* ((defined(HAVE_POLL) || defined(HAVE_PPOLL)) && !defined(HAVE_BROKEN_POLL)) && defined(HAVE_SYS_DEVPOLL_H) */
-#if (defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL)) && defined(HAVE_SYS_DEVPOLL_H)
+#if ((defined(HAVE_POLL) || defined(HAVE_PPOLL)) && !defined(HAVE_BROKEN_POLL)) && defined(HAVE_SYS_DEVPOLL_H)
PyDoc_STRVAR(select_devpoll_modify__doc__,
"modify($self, fd,\n"
return return_value;
}
-#endif /* (defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL)) && defined(HAVE_SYS_DEVPOLL_H) */
+#endif /* ((defined(HAVE_POLL) || defined(HAVE_PPOLL)) && !defined(HAVE_BROKEN_POLL)) && defined(HAVE_SYS_DEVPOLL_H) */
-#if (defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL)) && defined(HAVE_SYS_DEVPOLL_H)
+#if ((defined(HAVE_POLL) || defined(HAVE_PPOLL)) && !defined(HAVE_BROKEN_POLL)) && defined(HAVE_SYS_DEVPOLL_H)
PyDoc_STRVAR(select_devpoll_unregister__doc__,
"unregister($self, fd, /)\n"
return return_value;
}
-#endif /* (defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL)) && defined(HAVE_SYS_DEVPOLL_H) */
+#endif /* ((defined(HAVE_POLL) || defined(HAVE_PPOLL)) && !defined(HAVE_BROKEN_POLL)) && defined(HAVE_SYS_DEVPOLL_H) */
-#if (defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL)) && defined(HAVE_SYS_DEVPOLL_H)
+#if ((defined(HAVE_POLL) || defined(HAVE_PPOLL)) && !defined(HAVE_BROKEN_POLL)) && defined(HAVE_SYS_DEVPOLL_H)
PyDoc_STRVAR(select_devpoll_poll__doc__,
"poll($self, timeout=None, /)\n"
return return_value;
}
-#endif /* (defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL)) && defined(HAVE_SYS_DEVPOLL_H) */
+#endif /* ((defined(HAVE_POLL) || defined(HAVE_PPOLL)) && !defined(HAVE_BROKEN_POLL)) && defined(HAVE_SYS_DEVPOLL_H) */
-#if (defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL)) && defined(HAVE_SYS_DEVPOLL_H)
+#if ((defined(HAVE_POLL) || defined(HAVE_PPOLL)) && !defined(HAVE_BROKEN_POLL)) && defined(HAVE_SYS_DEVPOLL_H)
PyDoc_STRVAR(select_devpoll_close__doc__,
"close($self, /)\n"
return return_value;
}
-#endif /* (defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL)) && defined(HAVE_SYS_DEVPOLL_H) */
+#endif /* ((defined(HAVE_POLL) || defined(HAVE_PPOLL)) && !defined(HAVE_BROKEN_POLL)) && defined(HAVE_SYS_DEVPOLL_H) */
-#if (defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL)) && defined(HAVE_SYS_DEVPOLL_H)
+#if ((defined(HAVE_POLL) || defined(HAVE_PPOLL)) && !defined(HAVE_BROKEN_POLL)) && defined(HAVE_SYS_DEVPOLL_H)
PyDoc_STRVAR(select_devpoll_fileno__doc__,
"fileno($self, /)\n"
return return_value;
}
-#endif /* (defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL)) && defined(HAVE_SYS_DEVPOLL_H) */
+#endif /* ((defined(HAVE_POLL) || defined(HAVE_PPOLL)) && !defined(HAVE_BROKEN_POLL)) && defined(HAVE_SYS_DEVPOLL_H) */
-#if (defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL))
+#if ((defined(HAVE_POLL) || defined(HAVE_PPOLL)) && !defined(HAVE_BROKEN_POLL))
PyDoc_STRVAR(select_poll__doc__,
"poll($module, /)\n"
return select_poll_impl(module);
}
-#endif /* (defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL)) */
+#endif /* ((defined(HAVE_POLL) || defined(HAVE_PPOLL)) && !defined(HAVE_BROKEN_POLL)) */
-#if (defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL)) && defined(HAVE_SYS_DEVPOLL_H)
+#if ((defined(HAVE_POLL) || defined(HAVE_PPOLL)) && !defined(HAVE_BROKEN_POLL)) && defined(HAVE_SYS_DEVPOLL_H)
PyDoc_STRVAR(select_devpoll__doc__,
"devpoll($module, /)\n"
return select_devpoll_impl(module);
}
-#endif /* (defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL)) && defined(HAVE_SYS_DEVPOLL_H) */
+#endif /* ((defined(HAVE_POLL) || defined(HAVE_PPOLL)) && !defined(HAVE_BROKEN_POLL)) && defined(HAVE_SYS_DEVPOLL_H) */
#if defined(HAVE_EPOLL)
#ifndef SELECT_KQUEUE_CONTROL_METHODDEF
#define SELECT_KQUEUE_CONTROL_METHODDEF
#endif /* !defined(SELECT_KQUEUE_CONTROL_METHODDEF) */
-/*[clinic end generated code: output=ae54d65938513132 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=52e3be5cc66cf1b6 input=a9049054013a1b77]*/
return ret;
}
-#if defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL)
+#if (defined(HAVE_POLL) || defined(HAVE_PPOLL)) && !defined(HAVE_BROKEN_POLL)
/*
* poll() support
*/
PyObject *result_list = NULL;
int poll_result, i, j;
PyObject *value = NULL, *num = NULL;
- PyTime_t timeout = -1, ms = -1, deadline = 0;
+ PyTime_t timeout = -1, deadline = 0;
int async_err = 0;
if (timeout_obj != Py_None) {
}
return NULL;
}
+ }
- ms = _PyTime_AsMilliseconds(timeout, _PyTime_ROUND_TIMEOUT);
- if (ms < INT_MIN || ms > INT_MAX) {
- PyErr_SetString(PyExc_OverflowError, "timeout is too large");
+#ifdef HAVE_PPOLL
+ struct timespec ts, *ts_p = NULL;
+
+ if (timeout_obj != Py_None) {
+ if (_PyTime_AsTimespec(timeout, &ts) < 0) {
return NULL;
}
if (timeout >= 0) {
- deadline = _PyDeadline_Init(timeout);
+ ts_p = &ts;
+ }
+ }
+#else
+ PyTime_t ms = -1;
+
+ if (timeout_obj != Py_None) {
+ ms = _PyTime_AsMilliseconds(timeout, _PyTime_ROUND_TIMEOUT);
+ if (ms < INT_MIN || ms > INT_MAX) {
+ PyErr_SetString(PyExc_OverflowError, "timeout is too large");
+ return NULL;
}
}
ms = -1;
#endif
}
+#endif
+
+ if (timeout >= 0) {
+ deadline = _PyDeadline_Init(timeout);
+ }
/* Avoid concurrent poll() invocation, issue 8865 */
if (self->poll_running) {
do {
Py_BEGIN_ALLOW_THREADS
errno = 0;
+#ifdef HAVE_PPOLL
+ poll_result = ppoll(self->ufds, self->ufd_len, ts_p, NULL);
+#else
poll_result = poll(self->ufds, self->ufd_len, (int)ms);
+#endif
Py_END_ALLOW_THREADS
if (errno != EINTR)
poll_result = 0;
break;
}
+#ifdef HAVE_PPOLL
+ if (_PyTime_AsTimespec(timeout, &ts) < 0) {
+ poll_result = -1;
+ break;
+ }
+ assert(ts_p == &ts);
+#else
ms = _PyTime_AsMilliseconds(timeout, _PyTime_ROUND_CEILING);
- /* retry poll() with the recomputed timeout */
+#endif
+ /* retry poll()/ppoll() with the recomputed timeout */
}
} while (1);
#include "clinic/selectmodule.c.h"
-#if defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL)
+#if (defined(HAVE_POLL) || defined(HAVE_PPOLL)) && !defined(HAVE_BROKEN_POLL)
static PyMethodDef poll_methods[] = {
SELECT_POLL_REGISTER_METHODDEF
ADD_INT(PIPE_BUF);
#endif
-#if defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL)
+#if (defined(HAVE_POLL) || defined(HAVE_PPOLL)) && !defined(HAVE_BROKEN_POLL)
#ifdef __APPLE__
if (select_have_broken_poll()) {
if (PyObject_DelAttrString(m, "poll") == -1) {
then :
printf "%s\n" "#define HAVE_POLL 1" >>confdefs.h
+fi
+ac_fn_c_check_func "$LINENO" "ppoll" "ac_cv_func_ppoll"
+if test "x$ac_cv_func_ppoll" = xyes
+then :
+ printf "%s\n" "#define HAVE_PPOLL 1" >>confdefs.h
+
fi
ac_fn_c_check_func "$LINENO" "posix_fadvise" "ac_cv_func_posix_fadvise"
if test "x$ac_cv_func_posix_fadvise" = xyes
getspnam getuid getwd grantpt if_nameindex initgroups kill killpg lchown linkat \
lockf lstat lutimes madvise mbrtowc memrchr mkdirat mkfifo mkfifoat \
mknod mknodat mktime mmap mremap nice openat opendir pathconf pause pipe \
- pipe2 plock poll posix_fadvise posix_fallocate posix_openpt posix_spawn posix_spawnp \
+ pipe2 plock poll ppoll posix_fadvise posix_fallocate posix_openpt posix_spawn posix_spawnp \
posix_spawn_file_actions_addclosefrom_np \
pread preadv preadv2 process_vm_readv \
pthread_cond_timedwait_relative_np pthread_condattr_setclock pthread_init \
function. */
#undef HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSEFROM_NP
+/* Define to 1 if you have the 'ppoll' function. */
+#undef HAVE_PPOLL
+
/* Define to 1 if you have the 'pread' function. */
#undef HAVE_PREAD