17db96d56Sopenharmony_ci/* select - Module containing unix select(2) call. 27db96d56Sopenharmony_ci Under Unix, the file descriptors are small integers. 37db96d56Sopenharmony_ci Under Win32, select only exists for sockets, and sockets may 47db96d56Sopenharmony_ci have any value except INVALID_SOCKET. 57db96d56Sopenharmony_ci*/ 67db96d56Sopenharmony_ci 77db96d56Sopenharmony_ci#ifndef Py_BUILD_CORE_BUILTIN 87db96d56Sopenharmony_ci# define Py_BUILD_CORE_MODULE 1 97db96d56Sopenharmony_ci#endif 107db96d56Sopenharmony_ci 117db96d56Sopenharmony_ci#if defined(HAVE_POLL_H) && !defined(_GNU_SOURCE) 127db96d56Sopenharmony_ci# define _GNU_SOURCE 137db96d56Sopenharmony_ci#endif 147db96d56Sopenharmony_ci 157db96d56Sopenharmony_ci#include "Python.h" 167db96d56Sopenharmony_ci#include "pycore_fileutils.h" // _Py_set_inheritable() 177db96d56Sopenharmony_ci#include "structmember.h" // PyMemberDef 187db96d56Sopenharmony_ci 197db96d56Sopenharmony_ci#ifdef HAVE_SYS_DEVPOLL_H 207db96d56Sopenharmony_ci#include <sys/resource.h> 217db96d56Sopenharmony_ci#include <sys/devpoll.h> 227db96d56Sopenharmony_ci#include <sys/types.h> 237db96d56Sopenharmony_ci#include <sys/stat.h> 247db96d56Sopenharmony_ci#include <fcntl.h> 257db96d56Sopenharmony_ci#endif 267db96d56Sopenharmony_ci 277db96d56Sopenharmony_ci#ifdef __APPLE__ 287db96d56Sopenharmony_ci /* Perform runtime testing for a broken poll on OSX to make it easier 297db96d56Sopenharmony_ci * to use the same binary on multiple releases of the OS. 307db96d56Sopenharmony_ci */ 317db96d56Sopenharmony_ci#undef HAVE_BROKEN_POLL 327db96d56Sopenharmony_ci#endif 337db96d56Sopenharmony_ci 347db96d56Sopenharmony_ci/* Windows #defines FD_SETSIZE to 64 if FD_SETSIZE isn't already defined. 357db96d56Sopenharmony_ci 64 is too small (too many people have bumped into that limit). 367db96d56Sopenharmony_ci Here we boost it. 377db96d56Sopenharmony_ci Users who want even more than the boosted limit should #define 387db96d56Sopenharmony_ci FD_SETSIZE higher before this; e.g., via compiler /D switch. 397db96d56Sopenharmony_ci*/ 407db96d56Sopenharmony_ci#if defined(MS_WINDOWS) && !defined(FD_SETSIZE) 417db96d56Sopenharmony_ci#define FD_SETSIZE 512 427db96d56Sopenharmony_ci#endif 437db96d56Sopenharmony_ci 447db96d56Sopenharmony_ci#if defined(HAVE_POLL_H) 457db96d56Sopenharmony_ci#include <poll.h> 467db96d56Sopenharmony_ci#elif defined(HAVE_SYS_POLL_H) 477db96d56Sopenharmony_ci#include <sys/poll.h> 487db96d56Sopenharmony_ci#endif 497db96d56Sopenharmony_ci 507db96d56Sopenharmony_ci#ifdef __sgi 517db96d56Sopenharmony_ci/* This is missing from unistd.h */ 527db96d56Sopenharmony_ciextern void bzero(void *, int); 537db96d56Sopenharmony_ci#endif 547db96d56Sopenharmony_ci 557db96d56Sopenharmony_ci#ifdef HAVE_SYS_TYPES_H 567db96d56Sopenharmony_ci#include <sys/types.h> 577db96d56Sopenharmony_ci#endif 587db96d56Sopenharmony_ci 597db96d56Sopenharmony_ci#ifdef MS_WINDOWS 607db96d56Sopenharmony_ci# define WIN32_LEAN_AND_MEAN 617db96d56Sopenharmony_ci# include <winsock.h> 627db96d56Sopenharmony_ci#else 637db96d56Sopenharmony_ci# define SOCKET int 647db96d56Sopenharmony_ci#endif 657db96d56Sopenharmony_ci 667db96d56Sopenharmony_ci// WASI SDK 16 does not have POLLPRIO, define as no-op 677db96d56Sopenharmony_ci#if defined(__wasi__) && !defined(POLLPRI) 687db96d56Sopenharmony_ci# define POLLPRI 0 697db96d56Sopenharmony_ci#endif 707db96d56Sopenharmony_ci 717db96d56Sopenharmony_citypedef struct { 727db96d56Sopenharmony_ci PyObject *close; 737db96d56Sopenharmony_ci PyTypeObject *poll_Type; 747db96d56Sopenharmony_ci PyTypeObject *devpoll_Type; 757db96d56Sopenharmony_ci PyTypeObject *pyEpoll_Type; 767db96d56Sopenharmony_ci PyTypeObject *kqueue_event_Type; 777db96d56Sopenharmony_ci PyTypeObject *kqueue_queue_Type; 787db96d56Sopenharmony_ci} _selectstate; 797db96d56Sopenharmony_ci 807db96d56Sopenharmony_cistatic struct PyModuleDef selectmodule; 817db96d56Sopenharmony_ci 827db96d56Sopenharmony_cistatic inline _selectstate* 837db96d56Sopenharmony_ciget_select_state(PyObject *module) 847db96d56Sopenharmony_ci{ 857db96d56Sopenharmony_ci void *state = PyModule_GetState(module); 867db96d56Sopenharmony_ci assert(state != NULL); 877db96d56Sopenharmony_ci return (_selectstate *)state; 887db96d56Sopenharmony_ci} 897db96d56Sopenharmony_ci 907db96d56Sopenharmony_ci#define _selectstate_by_type(type) get_select_state(PyType_GetModule(type)) 917db96d56Sopenharmony_ci 927db96d56Sopenharmony_ci/*[clinic input] 937db96d56Sopenharmony_cimodule select 947db96d56Sopenharmony_ciclass select.poll "pollObject *" "_selectstate_by_type(type)->poll_Type" 957db96d56Sopenharmony_ciclass select.devpoll "devpollObject *" "_selectstate_by_type(type)->devpoll_Type" 967db96d56Sopenharmony_ciclass select.epoll "pyEpoll_Object *" "_selectstate_by_type(type)->pyEpoll_Type" 977db96d56Sopenharmony_ciclass select.kqueue "kqueue_queue_Object *" "_selectstate_by_type(type)->kqueue_queue_Type" 987db96d56Sopenharmony_ci[clinic start generated code]*/ 997db96d56Sopenharmony_ci/*[clinic end generated code: output=da39a3ee5e6b4b0d input=8072de35824aa327]*/ 1007db96d56Sopenharmony_ci 1017db96d56Sopenharmony_ci/* list of Python objects and their file descriptor */ 1027db96d56Sopenharmony_citypedef struct { 1037db96d56Sopenharmony_ci PyObject *obj; /* owned reference */ 1047db96d56Sopenharmony_ci SOCKET fd; 1057db96d56Sopenharmony_ci int sentinel; /* -1 == sentinel */ 1067db96d56Sopenharmony_ci} pylist; 1077db96d56Sopenharmony_ci 1087db96d56Sopenharmony_cistatic void 1097db96d56Sopenharmony_cireap_obj(pylist fd2obj[FD_SETSIZE + 1]) 1107db96d56Sopenharmony_ci{ 1117db96d56Sopenharmony_ci unsigned int i; 1127db96d56Sopenharmony_ci for (i = 0; i < (unsigned int)FD_SETSIZE + 1 && fd2obj[i].sentinel >= 0; i++) { 1137db96d56Sopenharmony_ci Py_CLEAR(fd2obj[i].obj); 1147db96d56Sopenharmony_ci } 1157db96d56Sopenharmony_ci fd2obj[0].sentinel = -1; 1167db96d56Sopenharmony_ci} 1177db96d56Sopenharmony_ci 1187db96d56Sopenharmony_ci 1197db96d56Sopenharmony_ci/* returns -1 and sets the Python exception if an error occurred, otherwise 1207db96d56Sopenharmony_ci returns a number >= 0 1217db96d56Sopenharmony_ci*/ 1227db96d56Sopenharmony_cistatic int 1237db96d56Sopenharmony_ciseq2set(PyObject *seq, fd_set *set, pylist fd2obj[FD_SETSIZE + 1]) 1247db96d56Sopenharmony_ci{ 1257db96d56Sopenharmony_ci int max = -1; 1267db96d56Sopenharmony_ci unsigned int index = 0; 1277db96d56Sopenharmony_ci Py_ssize_t i; 1287db96d56Sopenharmony_ci PyObject* fast_seq = NULL; 1297db96d56Sopenharmony_ci PyObject* o = NULL; 1307db96d56Sopenharmony_ci 1317db96d56Sopenharmony_ci fd2obj[0].obj = (PyObject*)0; /* set list to zero size */ 1327db96d56Sopenharmony_ci FD_ZERO(set); 1337db96d56Sopenharmony_ci 1347db96d56Sopenharmony_ci fast_seq = PySequence_Fast(seq, "arguments 1-3 must be sequences"); 1357db96d56Sopenharmony_ci if (!fast_seq) 1367db96d56Sopenharmony_ci return -1; 1377db96d56Sopenharmony_ci 1387db96d56Sopenharmony_ci for (i = 0; i < PySequence_Fast_GET_SIZE(fast_seq); i++) { 1397db96d56Sopenharmony_ci SOCKET v; 1407db96d56Sopenharmony_ci 1417db96d56Sopenharmony_ci /* any intervening fileno() calls could decr this refcnt */ 1427db96d56Sopenharmony_ci if (!(o = PySequence_Fast_GET_ITEM(fast_seq, i))) 1437db96d56Sopenharmony_ci goto finally; 1447db96d56Sopenharmony_ci 1457db96d56Sopenharmony_ci Py_INCREF(o); 1467db96d56Sopenharmony_ci v = PyObject_AsFileDescriptor( o ); 1477db96d56Sopenharmony_ci if (v == -1) goto finally; 1487db96d56Sopenharmony_ci 1497db96d56Sopenharmony_ci#if defined(_MSC_VER) 1507db96d56Sopenharmony_ci max = 0; /* not used for Win32 */ 1517db96d56Sopenharmony_ci#else /* !_MSC_VER */ 1527db96d56Sopenharmony_ci if (!_PyIsSelectable_fd(v)) { 1537db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, 1547db96d56Sopenharmony_ci "filedescriptor out of range in select()"); 1557db96d56Sopenharmony_ci goto finally; 1567db96d56Sopenharmony_ci } 1577db96d56Sopenharmony_ci if (v > max) 1587db96d56Sopenharmony_ci max = v; 1597db96d56Sopenharmony_ci#endif /* _MSC_VER */ 1607db96d56Sopenharmony_ci FD_SET(v, set); 1617db96d56Sopenharmony_ci 1627db96d56Sopenharmony_ci /* add object and its file descriptor to the list */ 1637db96d56Sopenharmony_ci if (index >= (unsigned int)FD_SETSIZE) { 1647db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, 1657db96d56Sopenharmony_ci "too many file descriptors in select()"); 1667db96d56Sopenharmony_ci goto finally; 1677db96d56Sopenharmony_ci } 1687db96d56Sopenharmony_ci fd2obj[index].obj = o; 1697db96d56Sopenharmony_ci fd2obj[index].fd = v; 1707db96d56Sopenharmony_ci fd2obj[index].sentinel = 0; 1717db96d56Sopenharmony_ci fd2obj[++index].sentinel = -1; 1727db96d56Sopenharmony_ci } 1737db96d56Sopenharmony_ci Py_DECREF(fast_seq); 1747db96d56Sopenharmony_ci return max+1; 1757db96d56Sopenharmony_ci 1767db96d56Sopenharmony_ci finally: 1777db96d56Sopenharmony_ci Py_XDECREF(o); 1787db96d56Sopenharmony_ci Py_DECREF(fast_seq); 1797db96d56Sopenharmony_ci return -1; 1807db96d56Sopenharmony_ci} 1817db96d56Sopenharmony_ci 1827db96d56Sopenharmony_ci/* returns NULL and sets the Python exception if an error occurred */ 1837db96d56Sopenharmony_cistatic PyObject * 1847db96d56Sopenharmony_ciset2list(fd_set *set, pylist fd2obj[FD_SETSIZE + 1]) 1857db96d56Sopenharmony_ci{ 1867db96d56Sopenharmony_ci int i, j, count=0; 1877db96d56Sopenharmony_ci PyObject *list, *o; 1887db96d56Sopenharmony_ci SOCKET fd; 1897db96d56Sopenharmony_ci 1907db96d56Sopenharmony_ci for (j = 0; fd2obj[j].sentinel >= 0; j++) { 1917db96d56Sopenharmony_ci if (FD_ISSET(fd2obj[j].fd, set)) 1927db96d56Sopenharmony_ci count++; 1937db96d56Sopenharmony_ci } 1947db96d56Sopenharmony_ci list = PyList_New(count); 1957db96d56Sopenharmony_ci if (!list) 1967db96d56Sopenharmony_ci return NULL; 1977db96d56Sopenharmony_ci 1987db96d56Sopenharmony_ci i = 0; 1997db96d56Sopenharmony_ci for (j = 0; fd2obj[j].sentinel >= 0; j++) { 2007db96d56Sopenharmony_ci fd = fd2obj[j].fd; 2017db96d56Sopenharmony_ci if (FD_ISSET(fd, set)) { 2027db96d56Sopenharmony_ci o = fd2obj[j].obj; 2037db96d56Sopenharmony_ci fd2obj[j].obj = NULL; 2047db96d56Sopenharmony_ci /* transfer ownership */ 2057db96d56Sopenharmony_ci if (PyList_SetItem(list, i, o) < 0) 2067db96d56Sopenharmony_ci goto finally; 2077db96d56Sopenharmony_ci 2087db96d56Sopenharmony_ci i++; 2097db96d56Sopenharmony_ci } 2107db96d56Sopenharmony_ci } 2117db96d56Sopenharmony_ci return list; 2127db96d56Sopenharmony_ci finally: 2137db96d56Sopenharmony_ci Py_DECREF(list); 2147db96d56Sopenharmony_ci return NULL; 2157db96d56Sopenharmony_ci} 2167db96d56Sopenharmony_ci 2177db96d56Sopenharmony_ci#undef SELECT_USES_HEAP 2187db96d56Sopenharmony_ci#if FD_SETSIZE > 1024 2197db96d56Sopenharmony_ci#define SELECT_USES_HEAP 2207db96d56Sopenharmony_ci#endif /* FD_SETSIZE > 1024 */ 2217db96d56Sopenharmony_ci 2227db96d56Sopenharmony_ci/*[clinic input] 2237db96d56Sopenharmony_ciselect.select 2247db96d56Sopenharmony_ci 2257db96d56Sopenharmony_ci rlist: object 2267db96d56Sopenharmony_ci wlist: object 2277db96d56Sopenharmony_ci xlist: object 2287db96d56Sopenharmony_ci timeout as timeout_obj: object = None 2297db96d56Sopenharmony_ci / 2307db96d56Sopenharmony_ci 2317db96d56Sopenharmony_ciWait until one or more file descriptors are ready for some kind of I/O. 2327db96d56Sopenharmony_ci 2337db96d56Sopenharmony_ciThe first three arguments are iterables of file descriptors to be waited for: 2347db96d56Sopenharmony_cirlist -- wait until ready for reading 2357db96d56Sopenharmony_ciwlist -- wait until ready for writing 2367db96d56Sopenharmony_cixlist -- wait for an "exceptional condition" 2377db96d56Sopenharmony_ciIf only one kind of condition is required, pass [] for the other lists. 2387db96d56Sopenharmony_ci 2397db96d56Sopenharmony_ciA file descriptor is either a socket or file object, or a small integer 2407db96d56Sopenharmony_cigotten from a fileno() method call on one of those. 2417db96d56Sopenharmony_ci 2427db96d56Sopenharmony_ciThe optional 4th argument specifies a timeout in seconds; it may be 2437db96d56Sopenharmony_cia floating point number to specify fractions of seconds. If it is absent 2447db96d56Sopenharmony_cior None, the call will never time out. 2457db96d56Sopenharmony_ci 2467db96d56Sopenharmony_ciThe return value is a tuple of three lists corresponding to the first three 2477db96d56Sopenharmony_ciarguments; each contains the subset of the corresponding file descriptors 2487db96d56Sopenharmony_cithat are ready. 2497db96d56Sopenharmony_ci 2507db96d56Sopenharmony_ci*** IMPORTANT NOTICE *** 2517db96d56Sopenharmony_ciOn Windows, only sockets are supported; on Unix, all file 2527db96d56Sopenharmony_cidescriptors can be used. 2537db96d56Sopenharmony_ci[clinic start generated code]*/ 2547db96d56Sopenharmony_ci 2557db96d56Sopenharmony_cistatic PyObject * 2567db96d56Sopenharmony_ciselect_select_impl(PyObject *module, PyObject *rlist, PyObject *wlist, 2577db96d56Sopenharmony_ci PyObject *xlist, PyObject *timeout_obj) 2587db96d56Sopenharmony_ci/*[clinic end generated code: output=2b3cfa824f7ae4cf input=e467f5d68033de00]*/ 2597db96d56Sopenharmony_ci{ 2607db96d56Sopenharmony_ci#ifdef SELECT_USES_HEAP 2617db96d56Sopenharmony_ci pylist *rfd2obj, *wfd2obj, *efd2obj; 2627db96d56Sopenharmony_ci#else /* !SELECT_USES_HEAP */ 2637db96d56Sopenharmony_ci /* XXX: All this should probably be implemented as follows: 2647db96d56Sopenharmony_ci * - find the highest descriptor we're interested in 2657db96d56Sopenharmony_ci * - add one 2667db96d56Sopenharmony_ci * - that's the size 2677db96d56Sopenharmony_ci * See: Stevens, APitUE, $12.5.1 2687db96d56Sopenharmony_ci */ 2697db96d56Sopenharmony_ci pylist rfd2obj[FD_SETSIZE + 1]; 2707db96d56Sopenharmony_ci pylist wfd2obj[FD_SETSIZE + 1]; 2717db96d56Sopenharmony_ci pylist efd2obj[FD_SETSIZE + 1]; 2727db96d56Sopenharmony_ci#endif /* SELECT_USES_HEAP */ 2737db96d56Sopenharmony_ci PyObject *ret = NULL; 2747db96d56Sopenharmony_ci fd_set ifdset, ofdset, efdset; 2757db96d56Sopenharmony_ci struct timeval tv, *tvp; 2767db96d56Sopenharmony_ci int imax, omax, emax, max; 2777db96d56Sopenharmony_ci int n; 2787db96d56Sopenharmony_ci _PyTime_t timeout, deadline = 0; 2797db96d56Sopenharmony_ci 2807db96d56Sopenharmony_ci if (timeout_obj == Py_None) 2817db96d56Sopenharmony_ci tvp = (struct timeval *)NULL; 2827db96d56Sopenharmony_ci else { 2837db96d56Sopenharmony_ci if (_PyTime_FromSecondsObject(&timeout, timeout_obj, 2847db96d56Sopenharmony_ci _PyTime_ROUND_TIMEOUT) < 0) { 2857db96d56Sopenharmony_ci if (PyErr_ExceptionMatches(PyExc_TypeError)) { 2867db96d56Sopenharmony_ci PyErr_SetString(PyExc_TypeError, 2877db96d56Sopenharmony_ci "timeout must be a float or None"); 2887db96d56Sopenharmony_ci } 2897db96d56Sopenharmony_ci return NULL; 2907db96d56Sopenharmony_ci } 2917db96d56Sopenharmony_ci 2927db96d56Sopenharmony_ci if (_PyTime_AsTimeval(timeout, &tv, _PyTime_ROUND_TIMEOUT) == -1) 2937db96d56Sopenharmony_ci return NULL; 2947db96d56Sopenharmony_ci if (tv.tv_sec < 0) { 2957db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, "timeout must be non-negative"); 2967db96d56Sopenharmony_ci return NULL; 2977db96d56Sopenharmony_ci } 2987db96d56Sopenharmony_ci tvp = &tv; 2997db96d56Sopenharmony_ci } 3007db96d56Sopenharmony_ci 3017db96d56Sopenharmony_ci#ifdef SELECT_USES_HEAP 3027db96d56Sopenharmony_ci /* Allocate memory for the lists */ 3037db96d56Sopenharmony_ci rfd2obj = PyMem_NEW(pylist, FD_SETSIZE + 1); 3047db96d56Sopenharmony_ci wfd2obj = PyMem_NEW(pylist, FD_SETSIZE + 1); 3057db96d56Sopenharmony_ci efd2obj = PyMem_NEW(pylist, FD_SETSIZE + 1); 3067db96d56Sopenharmony_ci if (rfd2obj == NULL || wfd2obj == NULL || efd2obj == NULL) { 3077db96d56Sopenharmony_ci if (rfd2obj) PyMem_Free(rfd2obj); 3087db96d56Sopenharmony_ci if (wfd2obj) PyMem_Free(wfd2obj); 3097db96d56Sopenharmony_ci if (efd2obj) PyMem_Free(efd2obj); 3107db96d56Sopenharmony_ci return PyErr_NoMemory(); 3117db96d56Sopenharmony_ci } 3127db96d56Sopenharmony_ci#endif /* SELECT_USES_HEAP */ 3137db96d56Sopenharmony_ci 3147db96d56Sopenharmony_ci /* Convert iterables to fd_sets, and get maximum fd number 3157db96d56Sopenharmony_ci * propagates the Python exception set in seq2set() 3167db96d56Sopenharmony_ci */ 3177db96d56Sopenharmony_ci rfd2obj[0].sentinel = -1; 3187db96d56Sopenharmony_ci wfd2obj[0].sentinel = -1; 3197db96d56Sopenharmony_ci efd2obj[0].sentinel = -1; 3207db96d56Sopenharmony_ci if ((imax = seq2set(rlist, &ifdset, rfd2obj)) < 0) 3217db96d56Sopenharmony_ci goto finally; 3227db96d56Sopenharmony_ci if ((omax = seq2set(wlist, &ofdset, wfd2obj)) < 0) 3237db96d56Sopenharmony_ci goto finally; 3247db96d56Sopenharmony_ci if ((emax = seq2set(xlist, &efdset, efd2obj)) < 0) 3257db96d56Sopenharmony_ci goto finally; 3267db96d56Sopenharmony_ci 3277db96d56Sopenharmony_ci max = imax; 3287db96d56Sopenharmony_ci if (omax > max) max = omax; 3297db96d56Sopenharmony_ci if (emax > max) max = emax; 3307db96d56Sopenharmony_ci 3317db96d56Sopenharmony_ci if (tvp) { 3327db96d56Sopenharmony_ci deadline = _PyDeadline_Init(timeout); 3337db96d56Sopenharmony_ci } 3347db96d56Sopenharmony_ci 3357db96d56Sopenharmony_ci do { 3367db96d56Sopenharmony_ci Py_BEGIN_ALLOW_THREADS 3377db96d56Sopenharmony_ci errno = 0; 3387db96d56Sopenharmony_ci n = select( 3397db96d56Sopenharmony_ci max, 3407db96d56Sopenharmony_ci imax ? &ifdset : NULL, 3417db96d56Sopenharmony_ci omax ? &ofdset : NULL, 3427db96d56Sopenharmony_ci emax ? &efdset : NULL, 3437db96d56Sopenharmony_ci tvp); 3447db96d56Sopenharmony_ci Py_END_ALLOW_THREADS 3457db96d56Sopenharmony_ci 3467db96d56Sopenharmony_ci if (errno != EINTR) 3477db96d56Sopenharmony_ci break; 3487db96d56Sopenharmony_ci 3497db96d56Sopenharmony_ci /* select() was interrupted by a signal */ 3507db96d56Sopenharmony_ci if (PyErr_CheckSignals()) 3517db96d56Sopenharmony_ci goto finally; 3527db96d56Sopenharmony_ci 3537db96d56Sopenharmony_ci if (tvp) { 3547db96d56Sopenharmony_ci timeout = _PyDeadline_Get(deadline); 3557db96d56Sopenharmony_ci if (timeout < 0) { 3567db96d56Sopenharmony_ci /* bpo-35310: lists were unmodified -- clear them explicitly */ 3577db96d56Sopenharmony_ci FD_ZERO(&ifdset); 3587db96d56Sopenharmony_ci FD_ZERO(&ofdset); 3597db96d56Sopenharmony_ci FD_ZERO(&efdset); 3607db96d56Sopenharmony_ci n = 0; 3617db96d56Sopenharmony_ci break; 3627db96d56Sopenharmony_ci } 3637db96d56Sopenharmony_ci _PyTime_AsTimeval_clamp(timeout, &tv, _PyTime_ROUND_CEILING); 3647db96d56Sopenharmony_ci /* retry select() with the recomputed timeout */ 3657db96d56Sopenharmony_ci } 3667db96d56Sopenharmony_ci } while (1); 3677db96d56Sopenharmony_ci 3687db96d56Sopenharmony_ci#ifdef MS_WINDOWS 3697db96d56Sopenharmony_ci if (n == SOCKET_ERROR) { 3707db96d56Sopenharmony_ci PyErr_SetExcFromWindowsErr(PyExc_OSError, WSAGetLastError()); 3717db96d56Sopenharmony_ci } 3727db96d56Sopenharmony_ci#else 3737db96d56Sopenharmony_ci if (n < 0) { 3747db96d56Sopenharmony_ci PyErr_SetFromErrno(PyExc_OSError); 3757db96d56Sopenharmony_ci } 3767db96d56Sopenharmony_ci#endif 3777db96d56Sopenharmony_ci else { 3787db96d56Sopenharmony_ci /* any of these three calls can raise an exception. it's more 3797db96d56Sopenharmony_ci convenient to test for this after all three calls... but 3807db96d56Sopenharmony_ci is that acceptable? 3817db96d56Sopenharmony_ci */ 3827db96d56Sopenharmony_ci rlist = set2list(&ifdset, rfd2obj); 3837db96d56Sopenharmony_ci wlist = set2list(&ofdset, wfd2obj); 3847db96d56Sopenharmony_ci xlist = set2list(&efdset, efd2obj); 3857db96d56Sopenharmony_ci if (PyErr_Occurred()) 3867db96d56Sopenharmony_ci ret = NULL; 3877db96d56Sopenharmony_ci else 3887db96d56Sopenharmony_ci ret = PyTuple_Pack(3, rlist, wlist, xlist); 3897db96d56Sopenharmony_ci 3907db96d56Sopenharmony_ci Py_XDECREF(rlist); 3917db96d56Sopenharmony_ci Py_XDECREF(wlist); 3927db96d56Sopenharmony_ci Py_XDECREF(xlist); 3937db96d56Sopenharmony_ci } 3947db96d56Sopenharmony_ci 3957db96d56Sopenharmony_ci finally: 3967db96d56Sopenharmony_ci reap_obj(rfd2obj); 3977db96d56Sopenharmony_ci reap_obj(wfd2obj); 3987db96d56Sopenharmony_ci reap_obj(efd2obj); 3997db96d56Sopenharmony_ci#ifdef SELECT_USES_HEAP 4007db96d56Sopenharmony_ci PyMem_Free(rfd2obj); 4017db96d56Sopenharmony_ci PyMem_Free(wfd2obj); 4027db96d56Sopenharmony_ci PyMem_Free(efd2obj); 4037db96d56Sopenharmony_ci#endif /* SELECT_USES_HEAP */ 4047db96d56Sopenharmony_ci return ret; 4057db96d56Sopenharmony_ci} 4067db96d56Sopenharmony_ci 4077db96d56Sopenharmony_ci#if defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL) 4087db96d56Sopenharmony_ci/* 4097db96d56Sopenharmony_ci * poll() support 4107db96d56Sopenharmony_ci */ 4117db96d56Sopenharmony_ci 4127db96d56Sopenharmony_citypedef struct { 4137db96d56Sopenharmony_ci PyObject_HEAD 4147db96d56Sopenharmony_ci PyObject *dict; 4157db96d56Sopenharmony_ci int ufd_uptodate; 4167db96d56Sopenharmony_ci int ufd_len; 4177db96d56Sopenharmony_ci struct pollfd *ufds; 4187db96d56Sopenharmony_ci int poll_running; 4197db96d56Sopenharmony_ci} pollObject; 4207db96d56Sopenharmony_ci 4217db96d56Sopenharmony_ci/* Update the malloc'ed array of pollfds to match the dictionary 4227db96d56Sopenharmony_ci contained within a pollObject. Return 1 on success, 0 on an error. 4237db96d56Sopenharmony_ci*/ 4247db96d56Sopenharmony_ci 4257db96d56Sopenharmony_cistatic int 4267db96d56Sopenharmony_ciupdate_ufd_array(pollObject *self) 4277db96d56Sopenharmony_ci{ 4287db96d56Sopenharmony_ci Py_ssize_t i, pos; 4297db96d56Sopenharmony_ci PyObject *key, *value; 4307db96d56Sopenharmony_ci struct pollfd *old_ufds = self->ufds; 4317db96d56Sopenharmony_ci 4327db96d56Sopenharmony_ci self->ufd_len = PyDict_GET_SIZE(self->dict); 4337db96d56Sopenharmony_ci PyMem_RESIZE(self->ufds, struct pollfd, self->ufd_len); 4347db96d56Sopenharmony_ci if (self->ufds == NULL) { 4357db96d56Sopenharmony_ci self->ufds = old_ufds; 4367db96d56Sopenharmony_ci PyErr_NoMemory(); 4377db96d56Sopenharmony_ci return 0; 4387db96d56Sopenharmony_ci } 4397db96d56Sopenharmony_ci 4407db96d56Sopenharmony_ci i = pos = 0; 4417db96d56Sopenharmony_ci while (PyDict_Next(self->dict, &pos, &key, &value)) { 4427db96d56Sopenharmony_ci assert(i < self->ufd_len); 4437db96d56Sopenharmony_ci /* Never overflow */ 4447db96d56Sopenharmony_ci self->ufds[i].fd = (int)PyLong_AsLong(key); 4457db96d56Sopenharmony_ci self->ufds[i].events = (short)(unsigned short)PyLong_AsLong(value); 4467db96d56Sopenharmony_ci i++; 4477db96d56Sopenharmony_ci } 4487db96d56Sopenharmony_ci assert(i == self->ufd_len); 4497db96d56Sopenharmony_ci self->ufd_uptodate = 1; 4507db96d56Sopenharmony_ci return 1; 4517db96d56Sopenharmony_ci} 4527db96d56Sopenharmony_ci 4537db96d56Sopenharmony_ci/*[clinic input] 4547db96d56Sopenharmony_ciselect.poll.register 4557db96d56Sopenharmony_ci 4567db96d56Sopenharmony_ci fd: fildes 4577db96d56Sopenharmony_ci either an integer, or an object with a fileno() method returning an int 4587db96d56Sopenharmony_ci eventmask: unsigned_short(c_default="POLLIN | POLLPRI | POLLOUT") = select.POLLIN | select.POLLPRI | select.POLLOUT 4597db96d56Sopenharmony_ci an optional bitmask describing the type of events to check for 4607db96d56Sopenharmony_ci / 4617db96d56Sopenharmony_ci 4627db96d56Sopenharmony_ciRegister a file descriptor with the polling object. 4637db96d56Sopenharmony_ci[clinic start generated code]*/ 4647db96d56Sopenharmony_ci 4657db96d56Sopenharmony_cistatic PyObject * 4667db96d56Sopenharmony_ciselect_poll_register_impl(pollObject *self, int fd, unsigned short eventmask) 4677db96d56Sopenharmony_ci/*[clinic end generated code: output=0dc7173c800a4a65 input=34e16cfb28d3c900]*/ 4687db96d56Sopenharmony_ci{ 4697db96d56Sopenharmony_ci PyObject *key, *value; 4707db96d56Sopenharmony_ci int err; 4717db96d56Sopenharmony_ci 4727db96d56Sopenharmony_ci /* Add entry to the internal dictionary: the key is the 4737db96d56Sopenharmony_ci file descriptor, and the value is the event mask. */ 4747db96d56Sopenharmony_ci key = PyLong_FromLong(fd); 4757db96d56Sopenharmony_ci if (key == NULL) 4767db96d56Sopenharmony_ci return NULL; 4777db96d56Sopenharmony_ci value = PyLong_FromLong(eventmask); 4787db96d56Sopenharmony_ci if (value == NULL) { 4797db96d56Sopenharmony_ci Py_DECREF(key); 4807db96d56Sopenharmony_ci return NULL; 4817db96d56Sopenharmony_ci } 4827db96d56Sopenharmony_ci err = PyDict_SetItem(self->dict, key, value); 4837db96d56Sopenharmony_ci Py_DECREF(key); 4847db96d56Sopenharmony_ci Py_DECREF(value); 4857db96d56Sopenharmony_ci if (err < 0) 4867db96d56Sopenharmony_ci return NULL; 4877db96d56Sopenharmony_ci 4887db96d56Sopenharmony_ci self->ufd_uptodate = 0; 4897db96d56Sopenharmony_ci 4907db96d56Sopenharmony_ci Py_RETURN_NONE; 4917db96d56Sopenharmony_ci} 4927db96d56Sopenharmony_ci 4937db96d56Sopenharmony_ci 4947db96d56Sopenharmony_ci/*[clinic input] 4957db96d56Sopenharmony_ciselect.poll.modify 4967db96d56Sopenharmony_ci 4977db96d56Sopenharmony_ci fd: fildes 4987db96d56Sopenharmony_ci either an integer, or an object with a fileno() method returning 4997db96d56Sopenharmony_ci an int 5007db96d56Sopenharmony_ci eventmask: unsigned_short 5017db96d56Sopenharmony_ci a bitmask describing the type of events to check for 5027db96d56Sopenharmony_ci / 5037db96d56Sopenharmony_ci 5047db96d56Sopenharmony_ciModify an already registered file descriptor. 5057db96d56Sopenharmony_ci[clinic start generated code]*/ 5067db96d56Sopenharmony_ci 5077db96d56Sopenharmony_cistatic PyObject * 5087db96d56Sopenharmony_ciselect_poll_modify_impl(pollObject *self, int fd, unsigned short eventmask) 5097db96d56Sopenharmony_ci/*[clinic end generated code: output=1a7b88bf079eff17 input=a8e383df075c32cf]*/ 5107db96d56Sopenharmony_ci{ 5117db96d56Sopenharmony_ci PyObject *key, *value; 5127db96d56Sopenharmony_ci int err; 5137db96d56Sopenharmony_ci 5147db96d56Sopenharmony_ci /* Modify registered fd */ 5157db96d56Sopenharmony_ci key = PyLong_FromLong(fd); 5167db96d56Sopenharmony_ci if (key == NULL) 5177db96d56Sopenharmony_ci return NULL; 5187db96d56Sopenharmony_ci err = PyDict_Contains(self->dict, key); 5197db96d56Sopenharmony_ci if (err < 0) { 5207db96d56Sopenharmony_ci Py_DECREF(key); 5217db96d56Sopenharmony_ci return NULL; 5227db96d56Sopenharmony_ci } 5237db96d56Sopenharmony_ci if (err == 0) { 5247db96d56Sopenharmony_ci errno = ENOENT; 5257db96d56Sopenharmony_ci PyErr_SetFromErrno(PyExc_OSError); 5267db96d56Sopenharmony_ci Py_DECREF(key); 5277db96d56Sopenharmony_ci return NULL; 5287db96d56Sopenharmony_ci } 5297db96d56Sopenharmony_ci value = PyLong_FromLong(eventmask); 5307db96d56Sopenharmony_ci if (value == NULL) { 5317db96d56Sopenharmony_ci Py_DECREF(key); 5327db96d56Sopenharmony_ci return NULL; 5337db96d56Sopenharmony_ci } 5347db96d56Sopenharmony_ci err = PyDict_SetItem(self->dict, key, value); 5357db96d56Sopenharmony_ci Py_DECREF(key); 5367db96d56Sopenharmony_ci Py_DECREF(value); 5377db96d56Sopenharmony_ci if (err < 0) 5387db96d56Sopenharmony_ci return NULL; 5397db96d56Sopenharmony_ci 5407db96d56Sopenharmony_ci self->ufd_uptodate = 0; 5417db96d56Sopenharmony_ci 5427db96d56Sopenharmony_ci Py_RETURN_NONE; 5437db96d56Sopenharmony_ci} 5447db96d56Sopenharmony_ci 5457db96d56Sopenharmony_ci 5467db96d56Sopenharmony_ci/*[clinic input] 5477db96d56Sopenharmony_ciselect.poll.unregister 5487db96d56Sopenharmony_ci 5497db96d56Sopenharmony_ci fd: fildes 5507db96d56Sopenharmony_ci / 5517db96d56Sopenharmony_ci 5527db96d56Sopenharmony_ciRemove a file descriptor being tracked by the polling object. 5537db96d56Sopenharmony_ci[clinic start generated code]*/ 5547db96d56Sopenharmony_ci 5557db96d56Sopenharmony_cistatic PyObject * 5567db96d56Sopenharmony_ciselect_poll_unregister_impl(pollObject *self, int fd) 5577db96d56Sopenharmony_ci/*[clinic end generated code: output=8c9f42e75e7d291b input=4b4fccc1040e79cb]*/ 5587db96d56Sopenharmony_ci{ 5597db96d56Sopenharmony_ci PyObject *key; 5607db96d56Sopenharmony_ci 5617db96d56Sopenharmony_ci /* Check whether the fd is already in the array */ 5627db96d56Sopenharmony_ci key = PyLong_FromLong(fd); 5637db96d56Sopenharmony_ci if (key == NULL) 5647db96d56Sopenharmony_ci return NULL; 5657db96d56Sopenharmony_ci 5667db96d56Sopenharmony_ci if (PyDict_DelItem(self->dict, key) == -1) { 5677db96d56Sopenharmony_ci Py_DECREF(key); 5687db96d56Sopenharmony_ci /* This will simply raise the KeyError set by PyDict_DelItem 5697db96d56Sopenharmony_ci if the file descriptor isn't registered. */ 5707db96d56Sopenharmony_ci return NULL; 5717db96d56Sopenharmony_ci } 5727db96d56Sopenharmony_ci 5737db96d56Sopenharmony_ci Py_DECREF(key); 5747db96d56Sopenharmony_ci self->ufd_uptodate = 0; 5757db96d56Sopenharmony_ci 5767db96d56Sopenharmony_ci Py_RETURN_NONE; 5777db96d56Sopenharmony_ci} 5787db96d56Sopenharmony_ci 5797db96d56Sopenharmony_ci/*[clinic input] 5807db96d56Sopenharmony_ciselect.poll.poll 5817db96d56Sopenharmony_ci 5827db96d56Sopenharmony_ci timeout as timeout_obj: object = None 5837db96d56Sopenharmony_ci The maximum time to wait in milliseconds, or else None (or a negative 5847db96d56Sopenharmony_ci value) to wait indefinitely. 5857db96d56Sopenharmony_ci / 5867db96d56Sopenharmony_ci 5877db96d56Sopenharmony_ciPolls the set of registered file descriptors. 5887db96d56Sopenharmony_ci 5897db96d56Sopenharmony_ciReturns a list containing any descriptors that have events or errors to 5907db96d56Sopenharmony_cireport, as a list of (fd, event) 2-tuples. 5917db96d56Sopenharmony_ci[clinic start generated code]*/ 5927db96d56Sopenharmony_ci 5937db96d56Sopenharmony_cistatic PyObject * 5947db96d56Sopenharmony_ciselect_poll_poll_impl(pollObject *self, PyObject *timeout_obj) 5957db96d56Sopenharmony_ci/*[clinic end generated code: output=876e837d193ed7e4 input=c2f6953ec45e5622]*/ 5967db96d56Sopenharmony_ci{ 5977db96d56Sopenharmony_ci PyObject *result_list = NULL; 5987db96d56Sopenharmony_ci int poll_result, i, j; 5997db96d56Sopenharmony_ci PyObject *value = NULL, *num = NULL; 6007db96d56Sopenharmony_ci _PyTime_t timeout = -1, ms = -1, deadline = 0; 6017db96d56Sopenharmony_ci int async_err = 0; 6027db96d56Sopenharmony_ci 6037db96d56Sopenharmony_ci if (timeout_obj != Py_None) { 6047db96d56Sopenharmony_ci if (_PyTime_FromMillisecondsObject(&timeout, timeout_obj, 6057db96d56Sopenharmony_ci _PyTime_ROUND_TIMEOUT) < 0) { 6067db96d56Sopenharmony_ci if (PyErr_ExceptionMatches(PyExc_TypeError)) { 6077db96d56Sopenharmony_ci PyErr_SetString(PyExc_TypeError, 6087db96d56Sopenharmony_ci "timeout must be an integer or None"); 6097db96d56Sopenharmony_ci } 6107db96d56Sopenharmony_ci return NULL; 6117db96d56Sopenharmony_ci } 6127db96d56Sopenharmony_ci 6137db96d56Sopenharmony_ci ms = _PyTime_AsMilliseconds(timeout, _PyTime_ROUND_TIMEOUT); 6147db96d56Sopenharmony_ci if (ms < INT_MIN || ms > INT_MAX) { 6157db96d56Sopenharmony_ci PyErr_SetString(PyExc_OverflowError, "timeout is too large"); 6167db96d56Sopenharmony_ci return NULL; 6177db96d56Sopenharmony_ci } 6187db96d56Sopenharmony_ci 6197db96d56Sopenharmony_ci if (timeout >= 0) { 6207db96d56Sopenharmony_ci deadline = _PyDeadline_Init(timeout); 6217db96d56Sopenharmony_ci } 6227db96d56Sopenharmony_ci } 6237db96d56Sopenharmony_ci 6247db96d56Sopenharmony_ci /* On some OSes, typically BSD-based ones, the timeout parameter of the 6257db96d56Sopenharmony_ci poll() syscall, when negative, must be exactly INFTIM, where defined, 6267db96d56Sopenharmony_ci or -1. See issue 31334. */ 6277db96d56Sopenharmony_ci if (ms < 0) { 6287db96d56Sopenharmony_ci#ifdef INFTIM 6297db96d56Sopenharmony_ci ms = INFTIM; 6307db96d56Sopenharmony_ci#else 6317db96d56Sopenharmony_ci ms = -1; 6327db96d56Sopenharmony_ci#endif 6337db96d56Sopenharmony_ci } 6347db96d56Sopenharmony_ci 6357db96d56Sopenharmony_ci /* Avoid concurrent poll() invocation, issue 8865 */ 6367db96d56Sopenharmony_ci if (self->poll_running) { 6377db96d56Sopenharmony_ci PyErr_SetString(PyExc_RuntimeError, 6387db96d56Sopenharmony_ci "concurrent poll() invocation"); 6397db96d56Sopenharmony_ci return NULL; 6407db96d56Sopenharmony_ci } 6417db96d56Sopenharmony_ci 6427db96d56Sopenharmony_ci /* Ensure the ufd array is up to date */ 6437db96d56Sopenharmony_ci if (!self->ufd_uptodate) 6447db96d56Sopenharmony_ci if (update_ufd_array(self) == 0) 6457db96d56Sopenharmony_ci return NULL; 6467db96d56Sopenharmony_ci 6477db96d56Sopenharmony_ci self->poll_running = 1; 6487db96d56Sopenharmony_ci 6497db96d56Sopenharmony_ci /* call poll() */ 6507db96d56Sopenharmony_ci async_err = 0; 6517db96d56Sopenharmony_ci do { 6527db96d56Sopenharmony_ci Py_BEGIN_ALLOW_THREADS 6537db96d56Sopenharmony_ci errno = 0; 6547db96d56Sopenharmony_ci poll_result = poll(self->ufds, self->ufd_len, (int)ms); 6557db96d56Sopenharmony_ci Py_END_ALLOW_THREADS 6567db96d56Sopenharmony_ci 6577db96d56Sopenharmony_ci if (errno != EINTR) 6587db96d56Sopenharmony_ci break; 6597db96d56Sopenharmony_ci 6607db96d56Sopenharmony_ci /* poll() was interrupted by a signal */ 6617db96d56Sopenharmony_ci if (PyErr_CheckSignals()) { 6627db96d56Sopenharmony_ci async_err = 1; 6637db96d56Sopenharmony_ci break; 6647db96d56Sopenharmony_ci } 6657db96d56Sopenharmony_ci 6667db96d56Sopenharmony_ci if (timeout >= 0) { 6677db96d56Sopenharmony_ci timeout = _PyDeadline_Get(deadline); 6687db96d56Sopenharmony_ci if (timeout < 0) { 6697db96d56Sopenharmony_ci poll_result = 0; 6707db96d56Sopenharmony_ci break; 6717db96d56Sopenharmony_ci } 6727db96d56Sopenharmony_ci ms = _PyTime_AsMilliseconds(timeout, _PyTime_ROUND_CEILING); 6737db96d56Sopenharmony_ci /* retry poll() with the recomputed timeout */ 6747db96d56Sopenharmony_ci } 6757db96d56Sopenharmony_ci } while (1); 6767db96d56Sopenharmony_ci 6777db96d56Sopenharmony_ci self->poll_running = 0; 6787db96d56Sopenharmony_ci 6797db96d56Sopenharmony_ci if (poll_result < 0) { 6807db96d56Sopenharmony_ci if (!async_err) 6817db96d56Sopenharmony_ci PyErr_SetFromErrno(PyExc_OSError); 6827db96d56Sopenharmony_ci return NULL; 6837db96d56Sopenharmony_ci } 6847db96d56Sopenharmony_ci 6857db96d56Sopenharmony_ci /* build the result list */ 6867db96d56Sopenharmony_ci 6877db96d56Sopenharmony_ci result_list = PyList_New(poll_result); 6887db96d56Sopenharmony_ci if (!result_list) 6897db96d56Sopenharmony_ci return NULL; 6907db96d56Sopenharmony_ci 6917db96d56Sopenharmony_ci for (i = 0, j = 0; j < poll_result; j++) { 6927db96d56Sopenharmony_ci /* skip to the next fired descriptor */ 6937db96d56Sopenharmony_ci while (!self->ufds[i].revents) { 6947db96d56Sopenharmony_ci i++; 6957db96d56Sopenharmony_ci } 6967db96d56Sopenharmony_ci /* if we hit a NULL return, set value to NULL 6977db96d56Sopenharmony_ci and break out of loop; code at end will 6987db96d56Sopenharmony_ci clean up result_list */ 6997db96d56Sopenharmony_ci value = PyTuple_New(2); 7007db96d56Sopenharmony_ci if (value == NULL) 7017db96d56Sopenharmony_ci goto error; 7027db96d56Sopenharmony_ci num = PyLong_FromLong(self->ufds[i].fd); 7037db96d56Sopenharmony_ci if (num == NULL) { 7047db96d56Sopenharmony_ci Py_DECREF(value); 7057db96d56Sopenharmony_ci goto error; 7067db96d56Sopenharmony_ci } 7077db96d56Sopenharmony_ci PyTuple_SET_ITEM(value, 0, num); 7087db96d56Sopenharmony_ci 7097db96d56Sopenharmony_ci /* The &0xffff is a workaround for AIX. 'revents' 7107db96d56Sopenharmony_ci is a 16-bit short, and IBM assigned POLLNVAL 7117db96d56Sopenharmony_ci to be 0x8000, so the conversion to int results 7127db96d56Sopenharmony_ci in a negative number. See SF bug #923315. */ 7137db96d56Sopenharmony_ci num = PyLong_FromLong(self->ufds[i].revents & 0xffff); 7147db96d56Sopenharmony_ci if (num == NULL) { 7157db96d56Sopenharmony_ci Py_DECREF(value); 7167db96d56Sopenharmony_ci goto error; 7177db96d56Sopenharmony_ci } 7187db96d56Sopenharmony_ci PyTuple_SET_ITEM(value, 1, num); 7197db96d56Sopenharmony_ci PyList_SET_ITEM(result_list, j, value); 7207db96d56Sopenharmony_ci i++; 7217db96d56Sopenharmony_ci } 7227db96d56Sopenharmony_ci return result_list; 7237db96d56Sopenharmony_ci 7247db96d56Sopenharmony_ci error: 7257db96d56Sopenharmony_ci Py_DECREF(result_list); 7267db96d56Sopenharmony_ci return NULL; 7277db96d56Sopenharmony_ci} 7287db96d56Sopenharmony_ci 7297db96d56Sopenharmony_cistatic pollObject * 7307db96d56Sopenharmony_cinewPollObject(PyObject *module) 7317db96d56Sopenharmony_ci{ 7327db96d56Sopenharmony_ci pollObject *self; 7337db96d56Sopenharmony_ci self = PyObject_New(pollObject, get_select_state(module)->poll_Type); 7347db96d56Sopenharmony_ci if (self == NULL) 7357db96d56Sopenharmony_ci return NULL; 7367db96d56Sopenharmony_ci /* ufd_uptodate is a Boolean, denoting whether the 7377db96d56Sopenharmony_ci array pointed to by ufds matches the contents of the dictionary. */ 7387db96d56Sopenharmony_ci self->ufd_uptodate = 0; 7397db96d56Sopenharmony_ci self->ufds = NULL; 7407db96d56Sopenharmony_ci self->poll_running = 0; 7417db96d56Sopenharmony_ci self->dict = PyDict_New(); 7427db96d56Sopenharmony_ci if (self->dict == NULL) { 7437db96d56Sopenharmony_ci Py_DECREF(self); 7447db96d56Sopenharmony_ci return NULL; 7457db96d56Sopenharmony_ci } 7467db96d56Sopenharmony_ci return self; 7477db96d56Sopenharmony_ci} 7487db96d56Sopenharmony_ci 7497db96d56Sopenharmony_cistatic void 7507db96d56Sopenharmony_cipoll_dealloc(pollObject *self) 7517db96d56Sopenharmony_ci{ 7527db96d56Sopenharmony_ci PyObject* type = (PyObject *)Py_TYPE(self); 7537db96d56Sopenharmony_ci if (self->ufds != NULL) 7547db96d56Sopenharmony_ci PyMem_Free(self->ufds); 7557db96d56Sopenharmony_ci Py_XDECREF(self->dict); 7567db96d56Sopenharmony_ci PyObject_Free(self); 7577db96d56Sopenharmony_ci Py_DECREF(type); 7587db96d56Sopenharmony_ci} 7597db96d56Sopenharmony_ci 7607db96d56Sopenharmony_ci 7617db96d56Sopenharmony_ci#ifdef HAVE_SYS_DEVPOLL_H 7627db96d56Sopenharmony_cistatic PyMethodDef devpoll_methods[]; 7637db96d56Sopenharmony_ci 7647db96d56Sopenharmony_citypedef struct { 7657db96d56Sopenharmony_ci PyObject_HEAD 7667db96d56Sopenharmony_ci int fd_devpoll; 7677db96d56Sopenharmony_ci int max_n_fds; 7687db96d56Sopenharmony_ci int n_fds; 7697db96d56Sopenharmony_ci struct pollfd *fds; 7707db96d56Sopenharmony_ci} devpollObject; 7717db96d56Sopenharmony_ci 7727db96d56Sopenharmony_cistatic PyObject * 7737db96d56Sopenharmony_cidevpoll_err_closed(void) 7747db96d56Sopenharmony_ci{ 7757db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, "I/O operation on closed devpoll object"); 7767db96d56Sopenharmony_ci return NULL; 7777db96d56Sopenharmony_ci} 7787db96d56Sopenharmony_ci 7797db96d56Sopenharmony_cistatic int devpoll_flush(devpollObject *self) 7807db96d56Sopenharmony_ci{ 7817db96d56Sopenharmony_ci int size, n; 7827db96d56Sopenharmony_ci 7837db96d56Sopenharmony_ci if (!self->n_fds) return 0; 7847db96d56Sopenharmony_ci 7857db96d56Sopenharmony_ci size = sizeof(struct pollfd)*self->n_fds; 7867db96d56Sopenharmony_ci self->n_fds = 0; 7877db96d56Sopenharmony_ci 7887db96d56Sopenharmony_ci n = _Py_write(self->fd_devpoll, self->fds, size); 7897db96d56Sopenharmony_ci if (n == -1) 7907db96d56Sopenharmony_ci return -1; 7917db96d56Sopenharmony_ci 7927db96d56Sopenharmony_ci if (n < size) { 7937db96d56Sopenharmony_ci /* 7947db96d56Sopenharmony_ci ** Data writed to /dev/poll is a binary data structure. It is not 7957db96d56Sopenharmony_ci ** clear what to do if a partial write occurred. For now, raise 7967db96d56Sopenharmony_ci ** an exception and see if we actually found this problem in 7977db96d56Sopenharmony_ci ** the wild. 7987db96d56Sopenharmony_ci ** See http://bugs.python.org/issue6397. 7997db96d56Sopenharmony_ci */ 8007db96d56Sopenharmony_ci PyErr_Format(PyExc_OSError, "failed to write all pollfds. " 8017db96d56Sopenharmony_ci "Please, report at http://bugs.python.org/. " 8027db96d56Sopenharmony_ci "Data to report: Size tried: %d, actual size written: %d.", 8037db96d56Sopenharmony_ci size, n); 8047db96d56Sopenharmony_ci return -1; 8057db96d56Sopenharmony_ci } 8067db96d56Sopenharmony_ci return 0; 8077db96d56Sopenharmony_ci} 8087db96d56Sopenharmony_ci 8097db96d56Sopenharmony_cistatic PyObject * 8107db96d56Sopenharmony_ciinternal_devpoll_register(devpollObject *self, int fd, 8117db96d56Sopenharmony_ci unsigned short events, int remove) 8127db96d56Sopenharmony_ci{ 8137db96d56Sopenharmony_ci if (self->fd_devpoll < 0) 8147db96d56Sopenharmony_ci return devpoll_err_closed(); 8157db96d56Sopenharmony_ci 8167db96d56Sopenharmony_ci if (remove) { 8177db96d56Sopenharmony_ci self->fds[self->n_fds].fd = fd; 8187db96d56Sopenharmony_ci self->fds[self->n_fds].events = POLLREMOVE; 8197db96d56Sopenharmony_ci 8207db96d56Sopenharmony_ci if (++self->n_fds == self->max_n_fds) { 8217db96d56Sopenharmony_ci if (devpoll_flush(self)) 8227db96d56Sopenharmony_ci return NULL; 8237db96d56Sopenharmony_ci } 8247db96d56Sopenharmony_ci } 8257db96d56Sopenharmony_ci 8267db96d56Sopenharmony_ci self->fds[self->n_fds].fd = fd; 8277db96d56Sopenharmony_ci self->fds[self->n_fds].events = (signed short)events; 8287db96d56Sopenharmony_ci 8297db96d56Sopenharmony_ci if (++self->n_fds == self->max_n_fds) { 8307db96d56Sopenharmony_ci if (devpoll_flush(self)) 8317db96d56Sopenharmony_ci return NULL; 8327db96d56Sopenharmony_ci } 8337db96d56Sopenharmony_ci 8347db96d56Sopenharmony_ci Py_RETURN_NONE; 8357db96d56Sopenharmony_ci} 8367db96d56Sopenharmony_ci 8377db96d56Sopenharmony_ci/*[clinic input] 8387db96d56Sopenharmony_ciselect.devpoll.register 8397db96d56Sopenharmony_ci 8407db96d56Sopenharmony_ci fd: fildes 8417db96d56Sopenharmony_ci either an integer, or an object with a fileno() method returning 8427db96d56Sopenharmony_ci an int 8437db96d56Sopenharmony_ci eventmask: unsigned_short(c_default="POLLIN | POLLPRI | POLLOUT") = select.POLLIN | select.POLLPRI | select.POLLOUT 8447db96d56Sopenharmony_ci an optional bitmask describing the type of events to check for 8457db96d56Sopenharmony_ci / 8467db96d56Sopenharmony_ci 8477db96d56Sopenharmony_ciRegister a file descriptor with the polling object. 8487db96d56Sopenharmony_ci[clinic start generated code]*/ 8497db96d56Sopenharmony_ci 8507db96d56Sopenharmony_cistatic PyObject * 8517db96d56Sopenharmony_ciselect_devpoll_register_impl(devpollObject *self, int fd, 8527db96d56Sopenharmony_ci unsigned short eventmask) 8537db96d56Sopenharmony_ci/*[clinic end generated code: output=6e07fe8b74abba0c input=22006fabe9567522]*/ 8547db96d56Sopenharmony_ci{ 8557db96d56Sopenharmony_ci return internal_devpoll_register(self, fd, eventmask, 0); 8567db96d56Sopenharmony_ci} 8577db96d56Sopenharmony_ci 8587db96d56Sopenharmony_ci/*[clinic input] 8597db96d56Sopenharmony_ciselect.devpoll.modify 8607db96d56Sopenharmony_ci 8617db96d56Sopenharmony_ci fd: fildes 8627db96d56Sopenharmony_ci either an integer, or an object with a fileno() method returning 8637db96d56Sopenharmony_ci an int 8647db96d56Sopenharmony_ci eventmask: unsigned_short(c_default="POLLIN | POLLPRI | POLLOUT") = select.POLLIN | select.POLLPRI | select.POLLOUT 8657db96d56Sopenharmony_ci an optional bitmask describing the type of events to check for 8667db96d56Sopenharmony_ci / 8677db96d56Sopenharmony_ci 8687db96d56Sopenharmony_ciModify a possible already registered file descriptor. 8697db96d56Sopenharmony_ci[clinic start generated code]*/ 8707db96d56Sopenharmony_ci 8717db96d56Sopenharmony_cistatic PyObject * 8727db96d56Sopenharmony_ciselect_devpoll_modify_impl(devpollObject *self, int fd, 8737db96d56Sopenharmony_ci unsigned short eventmask) 8747db96d56Sopenharmony_ci/*[clinic end generated code: output=bc2e6d23aaff98b4 input=09fa335db7cdc09e]*/ 8757db96d56Sopenharmony_ci{ 8767db96d56Sopenharmony_ci return internal_devpoll_register(self, fd, eventmask, 1); 8777db96d56Sopenharmony_ci} 8787db96d56Sopenharmony_ci 8797db96d56Sopenharmony_ci/*[clinic input] 8807db96d56Sopenharmony_ciselect.devpoll.unregister 8817db96d56Sopenharmony_ci 8827db96d56Sopenharmony_ci fd: fildes 8837db96d56Sopenharmony_ci / 8847db96d56Sopenharmony_ci 8857db96d56Sopenharmony_ciRemove a file descriptor being tracked by the polling object. 8867db96d56Sopenharmony_ci[clinic start generated code]*/ 8877db96d56Sopenharmony_ci 8887db96d56Sopenharmony_cistatic PyObject * 8897db96d56Sopenharmony_ciselect_devpoll_unregister_impl(devpollObject *self, int fd) 8907db96d56Sopenharmony_ci/*[clinic end generated code: output=95519ffa0c7d43fe input=b4ea42a4442fd467]*/ 8917db96d56Sopenharmony_ci{ 8927db96d56Sopenharmony_ci if (self->fd_devpoll < 0) 8937db96d56Sopenharmony_ci return devpoll_err_closed(); 8947db96d56Sopenharmony_ci 8957db96d56Sopenharmony_ci self->fds[self->n_fds].fd = fd; 8967db96d56Sopenharmony_ci self->fds[self->n_fds].events = POLLREMOVE; 8977db96d56Sopenharmony_ci 8987db96d56Sopenharmony_ci if (++self->n_fds == self->max_n_fds) { 8997db96d56Sopenharmony_ci if (devpoll_flush(self)) 9007db96d56Sopenharmony_ci return NULL; 9017db96d56Sopenharmony_ci } 9027db96d56Sopenharmony_ci 9037db96d56Sopenharmony_ci Py_RETURN_NONE; 9047db96d56Sopenharmony_ci} 9057db96d56Sopenharmony_ci 9067db96d56Sopenharmony_ci/*[clinic input] 9077db96d56Sopenharmony_ciselect.devpoll.poll 9087db96d56Sopenharmony_ci timeout as timeout_obj: object = None 9097db96d56Sopenharmony_ci The maximum time to wait in milliseconds, or else None (or a negative 9107db96d56Sopenharmony_ci value) to wait indefinitely. 9117db96d56Sopenharmony_ci / 9127db96d56Sopenharmony_ci 9137db96d56Sopenharmony_ciPolls the set of registered file descriptors. 9147db96d56Sopenharmony_ci 9157db96d56Sopenharmony_ciReturns a list containing any descriptors that have events or errors to 9167db96d56Sopenharmony_cireport, as a list of (fd, event) 2-tuples. 9177db96d56Sopenharmony_ci[clinic start generated code]*/ 9187db96d56Sopenharmony_ci 9197db96d56Sopenharmony_cistatic PyObject * 9207db96d56Sopenharmony_ciselect_devpoll_poll_impl(devpollObject *self, PyObject *timeout_obj) 9217db96d56Sopenharmony_ci/*[clinic end generated code: output=2654e5457cca0b3c input=3c3f0a355ec2bedb]*/ 9227db96d56Sopenharmony_ci{ 9237db96d56Sopenharmony_ci struct dvpoll dvp; 9247db96d56Sopenharmony_ci PyObject *result_list = NULL; 9257db96d56Sopenharmony_ci int poll_result, i; 9267db96d56Sopenharmony_ci PyObject *value, *num1, *num2; 9277db96d56Sopenharmony_ci _PyTime_t timeout, ms, deadline = 0; 9287db96d56Sopenharmony_ci 9297db96d56Sopenharmony_ci if (self->fd_devpoll < 0) 9307db96d56Sopenharmony_ci return devpoll_err_closed(); 9317db96d56Sopenharmony_ci 9327db96d56Sopenharmony_ci /* Check values for timeout */ 9337db96d56Sopenharmony_ci if (timeout_obj == Py_None) { 9347db96d56Sopenharmony_ci timeout = -1; 9357db96d56Sopenharmony_ci ms = -1; 9367db96d56Sopenharmony_ci } 9377db96d56Sopenharmony_ci else { 9387db96d56Sopenharmony_ci if (_PyTime_FromMillisecondsObject(&timeout, timeout_obj, 9397db96d56Sopenharmony_ci _PyTime_ROUND_TIMEOUT) < 0) { 9407db96d56Sopenharmony_ci if (PyErr_ExceptionMatches(PyExc_TypeError)) { 9417db96d56Sopenharmony_ci PyErr_SetString(PyExc_TypeError, 9427db96d56Sopenharmony_ci "timeout must be an integer or None"); 9437db96d56Sopenharmony_ci } 9447db96d56Sopenharmony_ci return NULL; 9457db96d56Sopenharmony_ci } 9467db96d56Sopenharmony_ci 9477db96d56Sopenharmony_ci ms = _PyTime_AsMilliseconds(timeout, _PyTime_ROUND_TIMEOUT); 9487db96d56Sopenharmony_ci if (ms < -1 || ms > INT_MAX) { 9497db96d56Sopenharmony_ci PyErr_SetString(PyExc_OverflowError, "timeout is too large"); 9507db96d56Sopenharmony_ci return NULL; 9517db96d56Sopenharmony_ci } 9527db96d56Sopenharmony_ci } 9537db96d56Sopenharmony_ci 9547db96d56Sopenharmony_ci if (devpoll_flush(self)) 9557db96d56Sopenharmony_ci return NULL; 9567db96d56Sopenharmony_ci 9577db96d56Sopenharmony_ci dvp.dp_fds = self->fds; 9587db96d56Sopenharmony_ci dvp.dp_nfds = self->max_n_fds; 9597db96d56Sopenharmony_ci dvp.dp_timeout = (int)ms; 9607db96d56Sopenharmony_ci 9617db96d56Sopenharmony_ci if (timeout >= 0) { 9627db96d56Sopenharmony_ci deadline = _PyDeadline_Init(timeout); 9637db96d56Sopenharmony_ci } 9647db96d56Sopenharmony_ci 9657db96d56Sopenharmony_ci do { 9667db96d56Sopenharmony_ci /* call devpoll() */ 9677db96d56Sopenharmony_ci Py_BEGIN_ALLOW_THREADS 9687db96d56Sopenharmony_ci errno = 0; 9697db96d56Sopenharmony_ci poll_result = ioctl(self->fd_devpoll, DP_POLL, &dvp); 9707db96d56Sopenharmony_ci Py_END_ALLOW_THREADS 9717db96d56Sopenharmony_ci 9727db96d56Sopenharmony_ci if (errno != EINTR) 9737db96d56Sopenharmony_ci break; 9747db96d56Sopenharmony_ci 9757db96d56Sopenharmony_ci /* devpoll() was interrupted by a signal */ 9767db96d56Sopenharmony_ci if (PyErr_CheckSignals()) 9777db96d56Sopenharmony_ci return NULL; 9787db96d56Sopenharmony_ci 9797db96d56Sopenharmony_ci if (timeout >= 0) { 9807db96d56Sopenharmony_ci timeout = _PyDeadline_Get(deadline); 9817db96d56Sopenharmony_ci if (timeout < 0) { 9827db96d56Sopenharmony_ci poll_result = 0; 9837db96d56Sopenharmony_ci break; 9847db96d56Sopenharmony_ci } 9857db96d56Sopenharmony_ci ms = _PyTime_AsMilliseconds(timeout, _PyTime_ROUND_CEILING); 9867db96d56Sopenharmony_ci dvp.dp_timeout = (int)ms; 9877db96d56Sopenharmony_ci /* retry devpoll() with the recomputed timeout */ 9887db96d56Sopenharmony_ci } 9897db96d56Sopenharmony_ci } while (1); 9907db96d56Sopenharmony_ci 9917db96d56Sopenharmony_ci if (poll_result < 0) { 9927db96d56Sopenharmony_ci PyErr_SetFromErrno(PyExc_OSError); 9937db96d56Sopenharmony_ci return NULL; 9947db96d56Sopenharmony_ci } 9957db96d56Sopenharmony_ci 9967db96d56Sopenharmony_ci /* build the result list */ 9977db96d56Sopenharmony_ci result_list = PyList_New(poll_result); 9987db96d56Sopenharmony_ci if (!result_list) 9997db96d56Sopenharmony_ci return NULL; 10007db96d56Sopenharmony_ci 10017db96d56Sopenharmony_ci for (i = 0; i < poll_result; i++) { 10027db96d56Sopenharmony_ci num1 = PyLong_FromLong(self->fds[i].fd); 10037db96d56Sopenharmony_ci num2 = PyLong_FromLong(self->fds[i].revents); 10047db96d56Sopenharmony_ci if ((num1 == NULL) || (num2 == NULL)) { 10057db96d56Sopenharmony_ci Py_XDECREF(num1); 10067db96d56Sopenharmony_ci Py_XDECREF(num2); 10077db96d56Sopenharmony_ci goto error; 10087db96d56Sopenharmony_ci } 10097db96d56Sopenharmony_ci value = PyTuple_Pack(2, num1, num2); 10107db96d56Sopenharmony_ci Py_DECREF(num1); 10117db96d56Sopenharmony_ci Py_DECREF(num2); 10127db96d56Sopenharmony_ci if (value == NULL) 10137db96d56Sopenharmony_ci goto error; 10147db96d56Sopenharmony_ci PyList_SET_ITEM(result_list, i, value); 10157db96d56Sopenharmony_ci } 10167db96d56Sopenharmony_ci 10177db96d56Sopenharmony_ci return result_list; 10187db96d56Sopenharmony_ci 10197db96d56Sopenharmony_ci error: 10207db96d56Sopenharmony_ci Py_DECREF(result_list); 10217db96d56Sopenharmony_ci return NULL; 10227db96d56Sopenharmony_ci} 10237db96d56Sopenharmony_ci 10247db96d56Sopenharmony_cistatic int 10257db96d56Sopenharmony_cidevpoll_internal_close(devpollObject *self) 10267db96d56Sopenharmony_ci{ 10277db96d56Sopenharmony_ci int save_errno = 0; 10287db96d56Sopenharmony_ci if (self->fd_devpoll >= 0) { 10297db96d56Sopenharmony_ci int fd = self->fd_devpoll; 10307db96d56Sopenharmony_ci self->fd_devpoll = -1; 10317db96d56Sopenharmony_ci Py_BEGIN_ALLOW_THREADS 10327db96d56Sopenharmony_ci if (close(fd) < 0) 10337db96d56Sopenharmony_ci save_errno = errno; 10347db96d56Sopenharmony_ci Py_END_ALLOW_THREADS 10357db96d56Sopenharmony_ci } 10367db96d56Sopenharmony_ci return save_errno; 10377db96d56Sopenharmony_ci} 10387db96d56Sopenharmony_ci 10397db96d56Sopenharmony_ci/*[clinic input] 10407db96d56Sopenharmony_ciselect.devpoll.close 10417db96d56Sopenharmony_ci 10427db96d56Sopenharmony_ciClose the devpoll file descriptor. 10437db96d56Sopenharmony_ci 10447db96d56Sopenharmony_ciFurther operations on the devpoll object will raise an exception. 10457db96d56Sopenharmony_ci[clinic start generated code]*/ 10467db96d56Sopenharmony_ci 10477db96d56Sopenharmony_cistatic PyObject * 10487db96d56Sopenharmony_ciselect_devpoll_close_impl(devpollObject *self) 10497db96d56Sopenharmony_ci/*[clinic end generated code: output=26b355bd6429f21b input=6273c30f5560a99b]*/ 10507db96d56Sopenharmony_ci{ 10517db96d56Sopenharmony_ci errno = devpoll_internal_close(self); 10527db96d56Sopenharmony_ci if (errno < 0) { 10537db96d56Sopenharmony_ci PyErr_SetFromErrno(PyExc_OSError); 10547db96d56Sopenharmony_ci return NULL; 10557db96d56Sopenharmony_ci } 10567db96d56Sopenharmony_ci Py_RETURN_NONE; 10577db96d56Sopenharmony_ci} 10587db96d56Sopenharmony_ci 10597db96d56Sopenharmony_cistatic PyObject* 10607db96d56Sopenharmony_cidevpoll_get_closed(devpollObject *self, void *Py_UNUSED(ignored)) 10617db96d56Sopenharmony_ci{ 10627db96d56Sopenharmony_ci if (self->fd_devpoll < 0) 10637db96d56Sopenharmony_ci Py_RETURN_TRUE; 10647db96d56Sopenharmony_ci else 10657db96d56Sopenharmony_ci Py_RETURN_FALSE; 10667db96d56Sopenharmony_ci} 10677db96d56Sopenharmony_ci 10687db96d56Sopenharmony_ci/*[clinic input] 10697db96d56Sopenharmony_ciselect.devpoll.fileno 10707db96d56Sopenharmony_ci 10717db96d56Sopenharmony_ciReturn the file descriptor. 10727db96d56Sopenharmony_ci[clinic start generated code]*/ 10737db96d56Sopenharmony_ci 10747db96d56Sopenharmony_cistatic PyObject * 10757db96d56Sopenharmony_ciselect_devpoll_fileno_impl(devpollObject *self) 10767db96d56Sopenharmony_ci/*[clinic end generated code: output=26920929f8d292f4 input=ef15331ebde6c368]*/ 10777db96d56Sopenharmony_ci{ 10787db96d56Sopenharmony_ci if (self->fd_devpoll < 0) 10797db96d56Sopenharmony_ci return devpoll_err_closed(); 10807db96d56Sopenharmony_ci return PyLong_FromLong(self->fd_devpoll); 10817db96d56Sopenharmony_ci} 10827db96d56Sopenharmony_ci 10837db96d56Sopenharmony_cistatic PyGetSetDef devpoll_getsetlist[] = { 10847db96d56Sopenharmony_ci {"closed", (getter)devpoll_get_closed, NULL, 10857db96d56Sopenharmony_ci "True if the devpoll object is closed"}, 10867db96d56Sopenharmony_ci {0}, 10877db96d56Sopenharmony_ci}; 10887db96d56Sopenharmony_ci 10897db96d56Sopenharmony_cistatic devpollObject * 10907db96d56Sopenharmony_cinewDevPollObject(PyObject *module) 10917db96d56Sopenharmony_ci{ 10927db96d56Sopenharmony_ci devpollObject *self; 10937db96d56Sopenharmony_ci int fd_devpoll, limit_result; 10947db96d56Sopenharmony_ci struct pollfd *fds; 10957db96d56Sopenharmony_ci struct rlimit limit; 10967db96d56Sopenharmony_ci 10977db96d56Sopenharmony_ci /* 10987db96d56Sopenharmony_ci ** If we try to process more that getrlimit() 10997db96d56Sopenharmony_ci ** fds, the kernel will give an error, so 11007db96d56Sopenharmony_ci ** we set the limit here. It is a dynamic 11017db96d56Sopenharmony_ci ** value, because we can change rlimit() anytime. 11027db96d56Sopenharmony_ci */ 11037db96d56Sopenharmony_ci limit_result = getrlimit(RLIMIT_NOFILE, &limit); 11047db96d56Sopenharmony_ci if (limit_result == -1) { 11057db96d56Sopenharmony_ci PyErr_SetFromErrno(PyExc_OSError); 11067db96d56Sopenharmony_ci return NULL; 11077db96d56Sopenharmony_ci } 11087db96d56Sopenharmony_ci 11097db96d56Sopenharmony_ci fd_devpoll = _Py_open("/dev/poll", O_RDWR); 11107db96d56Sopenharmony_ci if (fd_devpoll == -1) 11117db96d56Sopenharmony_ci return NULL; 11127db96d56Sopenharmony_ci 11137db96d56Sopenharmony_ci fds = PyMem_NEW(struct pollfd, limit.rlim_cur); 11147db96d56Sopenharmony_ci if (fds == NULL) { 11157db96d56Sopenharmony_ci close(fd_devpoll); 11167db96d56Sopenharmony_ci PyErr_NoMemory(); 11177db96d56Sopenharmony_ci return NULL; 11187db96d56Sopenharmony_ci } 11197db96d56Sopenharmony_ci 11207db96d56Sopenharmony_ci self = PyObject_New(devpollObject, get_select_state(module)->devpoll_Type); 11217db96d56Sopenharmony_ci if (self == NULL) { 11227db96d56Sopenharmony_ci close(fd_devpoll); 11237db96d56Sopenharmony_ci PyMem_Free(fds); 11247db96d56Sopenharmony_ci return NULL; 11257db96d56Sopenharmony_ci } 11267db96d56Sopenharmony_ci self->fd_devpoll = fd_devpoll; 11277db96d56Sopenharmony_ci self->max_n_fds = limit.rlim_cur; 11287db96d56Sopenharmony_ci self->n_fds = 0; 11297db96d56Sopenharmony_ci self->fds = fds; 11307db96d56Sopenharmony_ci 11317db96d56Sopenharmony_ci return self; 11327db96d56Sopenharmony_ci} 11337db96d56Sopenharmony_ci 11347db96d56Sopenharmony_cistatic void 11357db96d56Sopenharmony_cidevpoll_dealloc(devpollObject *self) 11367db96d56Sopenharmony_ci{ 11377db96d56Sopenharmony_ci PyObject *type = (PyObject *)Py_TYPE(self); 11387db96d56Sopenharmony_ci (void)devpoll_internal_close(self); 11397db96d56Sopenharmony_ci PyMem_Free(self->fds); 11407db96d56Sopenharmony_ci PyObject_Free(self); 11417db96d56Sopenharmony_ci Py_DECREF(type); 11427db96d56Sopenharmony_ci} 11437db96d56Sopenharmony_ci 11447db96d56Sopenharmony_cistatic PyType_Slot devpoll_Type_slots[] = { 11457db96d56Sopenharmony_ci {Py_tp_dealloc, devpoll_dealloc}, 11467db96d56Sopenharmony_ci {Py_tp_getset, devpoll_getsetlist}, 11477db96d56Sopenharmony_ci {Py_tp_methods, devpoll_methods}, 11487db96d56Sopenharmony_ci {0, 0}, 11497db96d56Sopenharmony_ci}; 11507db96d56Sopenharmony_ci 11517db96d56Sopenharmony_cistatic PyType_Spec devpoll_Type_spec = { 11527db96d56Sopenharmony_ci "select.devpoll", 11537db96d56Sopenharmony_ci sizeof(devpollObject), 11547db96d56Sopenharmony_ci 0, 11557db96d56Sopenharmony_ci Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION, 11567db96d56Sopenharmony_ci devpoll_Type_slots 11577db96d56Sopenharmony_ci}; 11587db96d56Sopenharmony_ci 11597db96d56Sopenharmony_ci#endif /* HAVE_SYS_DEVPOLL_H */ 11607db96d56Sopenharmony_ci 11617db96d56Sopenharmony_ci 11627db96d56Sopenharmony_ci/*[clinic input] 11637db96d56Sopenharmony_ciselect.poll 11647db96d56Sopenharmony_ci 11657db96d56Sopenharmony_ciReturns a polling object. 11667db96d56Sopenharmony_ci 11677db96d56Sopenharmony_ciThis object supports registering and unregistering file descriptors, and then 11687db96d56Sopenharmony_cipolling them for I/O events. 11697db96d56Sopenharmony_ci[clinic start generated code]*/ 11707db96d56Sopenharmony_ci 11717db96d56Sopenharmony_cistatic PyObject * 11727db96d56Sopenharmony_ciselect_poll_impl(PyObject *module) 11737db96d56Sopenharmony_ci/*[clinic end generated code: output=16a665a4e1d228c5 input=3f877909d5696bbf]*/ 11747db96d56Sopenharmony_ci{ 11757db96d56Sopenharmony_ci return (PyObject *)newPollObject(module); 11767db96d56Sopenharmony_ci} 11777db96d56Sopenharmony_ci 11787db96d56Sopenharmony_ci#ifdef HAVE_SYS_DEVPOLL_H 11797db96d56Sopenharmony_ci 11807db96d56Sopenharmony_ci/*[clinic input] 11817db96d56Sopenharmony_ciselect.devpoll 11827db96d56Sopenharmony_ci 11837db96d56Sopenharmony_ciReturns a polling object. 11847db96d56Sopenharmony_ci 11857db96d56Sopenharmony_ciThis object supports registering and unregistering file descriptors, and then 11867db96d56Sopenharmony_cipolling them for I/O events. 11877db96d56Sopenharmony_ci[clinic start generated code]*/ 11887db96d56Sopenharmony_ci 11897db96d56Sopenharmony_cistatic PyObject * 11907db96d56Sopenharmony_ciselect_devpoll_impl(PyObject *module) 11917db96d56Sopenharmony_ci/*[clinic end generated code: output=ea9213cc87fd9581 input=53a1af94564f00a3]*/ 11927db96d56Sopenharmony_ci{ 11937db96d56Sopenharmony_ci return (PyObject *)newDevPollObject(module); 11947db96d56Sopenharmony_ci} 11957db96d56Sopenharmony_ci#endif 11967db96d56Sopenharmony_ci 11977db96d56Sopenharmony_ci 11987db96d56Sopenharmony_ci#ifdef __APPLE__ 11997db96d56Sopenharmony_ci/* 12007db96d56Sopenharmony_ci * On some systems poll() sets errno on invalid file descriptors. We test 12017db96d56Sopenharmony_ci * for this at runtime because this bug may be fixed or introduced between 12027db96d56Sopenharmony_ci * OS releases. 12037db96d56Sopenharmony_ci */ 12047db96d56Sopenharmony_cistatic int select_have_broken_poll(void) 12057db96d56Sopenharmony_ci{ 12067db96d56Sopenharmony_ci int poll_test; 12077db96d56Sopenharmony_ci int filedes[2]; 12087db96d56Sopenharmony_ci 12097db96d56Sopenharmony_ci struct pollfd poll_struct = { 0, POLLIN|POLLPRI|POLLOUT, 0 }; 12107db96d56Sopenharmony_ci 12117db96d56Sopenharmony_ci /* Create a file descriptor to make invalid */ 12127db96d56Sopenharmony_ci if (pipe(filedes) < 0) { 12137db96d56Sopenharmony_ci return 1; 12147db96d56Sopenharmony_ci } 12157db96d56Sopenharmony_ci poll_struct.fd = filedes[0]; 12167db96d56Sopenharmony_ci close(filedes[0]); 12177db96d56Sopenharmony_ci close(filedes[1]); 12187db96d56Sopenharmony_ci poll_test = poll(&poll_struct, 1, 0); 12197db96d56Sopenharmony_ci if (poll_test < 0) { 12207db96d56Sopenharmony_ci return 1; 12217db96d56Sopenharmony_ci } else if (poll_test == 0 && poll_struct.revents != POLLNVAL) { 12227db96d56Sopenharmony_ci return 1; 12237db96d56Sopenharmony_ci } 12247db96d56Sopenharmony_ci return 0; 12257db96d56Sopenharmony_ci} 12267db96d56Sopenharmony_ci#endif /* __APPLE__ */ 12277db96d56Sopenharmony_ci 12287db96d56Sopenharmony_ci#endif /* HAVE_POLL */ 12297db96d56Sopenharmony_ci 12307db96d56Sopenharmony_ci#ifdef HAVE_EPOLL 12317db96d56Sopenharmony_ci/* ************************************************************************** 12327db96d56Sopenharmony_ci * epoll interface for Linux 2.6 12337db96d56Sopenharmony_ci * 12347db96d56Sopenharmony_ci * Written by Christian Heimes 12357db96d56Sopenharmony_ci * Inspired by Twisted's _epoll.pyx and select.poll() 12367db96d56Sopenharmony_ci */ 12377db96d56Sopenharmony_ci 12387db96d56Sopenharmony_ci#ifdef HAVE_SYS_EPOLL_H 12397db96d56Sopenharmony_ci#include <sys/epoll.h> 12407db96d56Sopenharmony_ci#endif 12417db96d56Sopenharmony_ci 12427db96d56Sopenharmony_citypedef struct { 12437db96d56Sopenharmony_ci PyObject_HEAD 12447db96d56Sopenharmony_ci SOCKET epfd; /* epoll control file descriptor */ 12457db96d56Sopenharmony_ci} pyEpoll_Object; 12467db96d56Sopenharmony_ci 12477db96d56Sopenharmony_cistatic PyObject * 12487db96d56Sopenharmony_cipyepoll_err_closed(void) 12497db96d56Sopenharmony_ci{ 12507db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, "I/O operation on closed epoll object"); 12517db96d56Sopenharmony_ci return NULL; 12527db96d56Sopenharmony_ci} 12537db96d56Sopenharmony_ci 12547db96d56Sopenharmony_cistatic int 12557db96d56Sopenharmony_cipyepoll_internal_close(pyEpoll_Object *self) 12567db96d56Sopenharmony_ci{ 12577db96d56Sopenharmony_ci int save_errno = 0; 12587db96d56Sopenharmony_ci if (self->epfd >= 0) { 12597db96d56Sopenharmony_ci int epfd = self->epfd; 12607db96d56Sopenharmony_ci self->epfd = -1; 12617db96d56Sopenharmony_ci Py_BEGIN_ALLOW_THREADS 12627db96d56Sopenharmony_ci if (close(epfd) < 0) 12637db96d56Sopenharmony_ci save_errno = errno; 12647db96d56Sopenharmony_ci Py_END_ALLOW_THREADS 12657db96d56Sopenharmony_ci } 12667db96d56Sopenharmony_ci return save_errno; 12677db96d56Sopenharmony_ci} 12687db96d56Sopenharmony_ci 12697db96d56Sopenharmony_cistatic PyObject * 12707db96d56Sopenharmony_cinewPyEpoll_Object(PyTypeObject *type, int sizehint, SOCKET fd) 12717db96d56Sopenharmony_ci{ 12727db96d56Sopenharmony_ci pyEpoll_Object *self; 12737db96d56Sopenharmony_ci assert(type != NULL); 12747db96d56Sopenharmony_ci allocfunc epoll_alloc = PyType_GetSlot(type, Py_tp_alloc); 12757db96d56Sopenharmony_ci assert(epoll_alloc != NULL); 12767db96d56Sopenharmony_ci self = (pyEpoll_Object *) epoll_alloc(type, 0); 12777db96d56Sopenharmony_ci if (self == NULL) 12787db96d56Sopenharmony_ci return NULL; 12797db96d56Sopenharmony_ci 12807db96d56Sopenharmony_ci if (fd == -1) { 12817db96d56Sopenharmony_ci Py_BEGIN_ALLOW_THREADS 12827db96d56Sopenharmony_ci#ifdef HAVE_EPOLL_CREATE1 12837db96d56Sopenharmony_ci self->epfd = epoll_create1(EPOLL_CLOEXEC); 12847db96d56Sopenharmony_ci#else 12857db96d56Sopenharmony_ci self->epfd = epoll_create(sizehint); 12867db96d56Sopenharmony_ci#endif 12877db96d56Sopenharmony_ci Py_END_ALLOW_THREADS 12887db96d56Sopenharmony_ci } 12897db96d56Sopenharmony_ci else { 12907db96d56Sopenharmony_ci self->epfd = fd; 12917db96d56Sopenharmony_ci } 12927db96d56Sopenharmony_ci if (self->epfd < 0) { 12937db96d56Sopenharmony_ci Py_DECREF(self); 12947db96d56Sopenharmony_ci PyErr_SetFromErrno(PyExc_OSError); 12957db96d56Sopenharmony_ci return NULL; 12967db96d56Sopenharmony_ci } 12977db96d56Sopenharmony_ci 12987db96d56Sopenharmony_ci#ifndef HAVE_EPOLL_CREATE1 12997db96d56Sopenharmony_ci if (fd == -1 && _Py_set_inheritable(self->epfd, 0, NULL) < 0) { 13007db96d56Sopenharmony_ci Py_DECREF(self); 13017db96d56Sopenharmony_ci return NULL; 13027db96d56Sopenharmony_ci } 13037db96d56Sopenharmony_ci#endif 13047db96d56Sopenharmony_ci 13057db96d56Sopenharmony_ci return (PyObject *)self; 13067db96d56Sopenharmony_ci} 13077db96d56Sopenharmony_ci 13087db96d56Sopenharmony_ci 13097db96d56Sopenharmony_ci/*[clinic input] 13107db96d56Sopenharmony_ci@classmethod 13117db96d56Sopenharmony_ciselect.epoll.__new__ 13127db96d56Sopenharmony_ci 13137db96d56Sopenharmony_ci sizehint: int = -1 13147db96d56Sopenharmony_ci The expected number of events to be registered. It must be positive, 13157db96d56Sopenharmony_ci or -1 to use the default. It is only used on older systems where 13167db96d56Sopenharmony_ci epoll_create1() is not available; otherwise it has no effect (though its 13177db96d56Sopenharmony_ci value is still checked). 13187db96d56Sopenharmony_ci flags: int = 0 13197db96d56Sopenharmony_ci Deprecated and completely ignored. However, when supplied, its value 13207db96d56Sopenharmony_ci must be 0 or select.EPOLL_CLOEXEC, otherwise OSError is raised. 13217db96d56Sopenharmony_ci 13227db96d56Sopenharmony_ciReturns an epolling object. 13237db96d56Sopenharmony_ci[clinic start generated code]*/ 13247db96d56Sopenharmony_ci 13257db96d56Sopenharmony_cistatic PyObject * 13267db96d56Sopenharmony_ciselect_epoll_impl(PyTypeObject *type, int sizehint, int flags) 13277db96d56Sopenharmony_ci/*[clinic end generated code: output=c87404e705013bb5 input=303e3295e7975e43]*/ 13287db96d56Sopenharmony_ci{ 13297db96d56Sopenharmony_ci if (sizehint == -1) { 13307db96d56Sopenharmony_ci sizehint = FD_SETSIZE - 1; 13317db96d56Sopenharmony_ci } 13327db96d56Sopenharmony_ci else if (sizehint <= 0) { 13337db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, "negative sizehint"); 13347db96d56Sopenharmony_ci return NULL; 13357db96d56Sopenharmony_ci } 13367db96d56Sopenharmony_ci 13377db96d56Sopenharmony_ci#ifdef HAVE_EPOLL_CREATE1 13387db96d56Sopenharmony_ci if (flags && flags != EPOLL_CLOEXEC) { 13397db96d56Sopenharmony_ci PyErr_SetString(PyExc_OSError, "invalid flags"); 13407db96d56Sopenharmony_ci return NULL; 13417db96d56Sopenharmony_ci } 13427db96d56Sopenharmony_ci#endif 13437db96d56Sopenharmony_ci 13447db96d56Sopenharmony_ci return newPyEpoll_Object(type, sizehint, -1); 13457db96d56Sopenharmony_ci} 13467db96d56Sopenharmony_ci 13477db96d56Sopenharmony_ci 13487db96d56Sopenharmony_cistatic void 13497db96d56Sopenharmony_cipyepoll_dealloc(pyEpoll_Object *self) 13507db96d56Sopenharmony_ci{ 13517db96d56Sopenharmony_ci PyTypeObject* type = Py_TYPE(self); 13527db96d56Sopenharmony_ci (void)pyepoll_internal_close(self); 13537db96d56Sopenharmony_ci freefunc epoll_free = PyType_GetSlot(type, Py_tp_free); 13547db96d56Sopenharmony_ci epoll_free((PyObject *)self); 13557db96d56Sopenharmony_ci Py_DECREF((PyObject *)type); 13567db96d56Sopenharmony_ci} 13577db96d56Sopenharmony_ci 13587db96d56Sopenharmony_ci/*[clinic input] 13597db96d56Sopenharmony_ciselect.epoll.close 13607db96d56Sopenharmony_ci 13617db96d56Sopenharmony_ciClose the epoll control file descriptor. 13627db96d56Sopenharmony_ci 13637db96d56Sopenharmony_ciFurther operations on the epoll object will raise an exception. 13647db96d56Sopenharmony_ci[clinic start generated code]*/ 13657db96d56Sopenharmony_ci 13667db96d56Sopenharmony_cistatic PyObject * 13677db96d56Sopenharmony_ciselect_epoll_close_impl(pyEpoll_Object *self) 13687db96d56Sopenharmony_ci/*[clinic end generated code: output=ee2144c446a1a435 input=ca6c66ba5a736bfd]*/ 13697db96d56Sopenharmony_ci{ 13707db96d56Sopenharmony_ci errno = pyepoll_internal_close(self); 13717db96d56Sopenharmony_ci if (errno < 0) { 13727db96d56Sopenharmony_ci PyErr_SetFromErrno(PyExc_OSError); 13737db96d56Sopenharmony_ci return NULL; 13747db96d56Sopenharmony_ci } 13757db96d56Sopenharmony_ci Py_RETURN_NONE; 13767db96d56Sopenharmony_ci} 13777db96d56Sopenharmony_ci 13787db96d56Sopenharmony_ci 13797db96d56Sopenharmony_cistatic PyObject* 13807db96d56Sopenharmony_cipyepoll_get_closed(pyEpoll_Object *self, void *Py_UNUSED(ignored)) 13817db96d56Sopenharmony_ci{ 13827db96d56Sopenharmony_ci if (self->epfd < 0) 13837db96d56Sopenharmony_ci Py_RETURN_TRUE; 13847db96d56Sopenharmony_ci else 13857db96d56Sopenharmony_ci Py_RETURN_FALSE; 13867db96d56Sopenharmony_ci} 13877db96d56Sopenharmony_ci 13887db96d56Sopenharmony_ci/*[clinic input] 13897db96d56Sopenharmony_ciselect.epoll.fileno 13907db96d56Sopenharmony_ci 13917db96d56Sopenharmony_ciReturn the epoll control file descriptor. 13927db96d56Sopenharmony_ci[clinic start generated code]*/ 13937db96d56Sopenharmony_ci 13947db96d56Sopenharmony_cistatic PyObject * 13957db96d56Sopenharmony_ciselect_epoll_fileno_impl(pyEpoll_Object *self) 13967db96d56Sopenharmony_ci/*[clinic end generated code: output=e171375fdc619ba3 input=c11091a6aee60b5c]*/ 13977db96d56Sopenharmony_ci{ 13987db96d56Sopenharmony_ci if (self->epfd < 0) 13997db96d56Sopenharmony_ci return pyepoll_err_closed(); 14007db96d56Sopenharmony_ci return PyLong_FromLong(self->epfd); 14017db96d56Sopenharmony_ci} 14027db96d56Sopenharmony_ci 14037db96d56Sopenharmony_ci 14047db96d56Sopenharmony_ci/*[clinic input] 14057db96d56Sopenharmony_ci@classmethod 14067db96d56Sopenharmony_ciselect.epoll.fromfd 14077db96d56Sopenharmony_ci 14087db96d56Sopenharmony_ci fd: int 14097db96d56Sopenharmony_ci / 14107db96d56Sopenharmony_ci 14117db96d56Sopenharmony_ciCreate an epoll object from a given control fd. 14127db96d56Sopenharmony_ci[clinic start generated code]*/ 14137db96d56Sopenharmony_ci 14147db96d56Sopenharmony_cistatic PyObject * 14157db96d56Sopenharmony_ciselect_epoll_fromfd_impl(PyTypeObject *type, int fd) 14167db96d56Sopenharmony_ci/*[clinic end generated code: output=c15de2a083524e8e input=faecefdb55e3046e]*/ 14177db96d56Sopenharmony_ci{ 14187db96d56Sopenharmony_ci SOCKET s_fd = (SOCKET)fd; 14197db96d56Sopenharmony_ci return newPyEpoll_Object(type, FD_SETSIZE - 1, s_fd); 14207db96d56Sopenharmony_ci} 14217db96d56Sopenharmony_ci 14227db96d56Sopenharmony_ci 14237db96d56Sopenharmony_cistatic PyObject * 14247db96d56Sopenharmony_cipyepoll_internal_ctl(int epfd, int op, int fd, unsigned int events) 14257db96d56Sopenharmony_ci{ 14267db96d56Sopenharmony_ci struct epoll_event ev; 14277db96d56Sopenharmony_ci int result; 14287db96d56Sopenharmony_ci 14297db96d56Sopenharmony_ci if (epfd < 0) 14307db96d56Sopenharmony_ci return pyepoll_err_closed(); 14317db96d56Sopenharmony_ci 14327db96d56Sopenharmony_ci switch (op) { 14337db96d56Sopenharmony_ci case EPOLL_CTL_ADD: 14347db96d56Sopenharmony_ci case EPOLL_CTL_MOD: 14357db96d56Sopenharmony_ci ev.events = events; 14367db96d56Sopenharmony_ci ev.data.fd = fd; 14377db96d56Sopenharmony_ci Py_BEGIN_ALLOW_THREADS 14387db96d56Sopenharmony_ci result = epoll_ctl(epfd, op, fd, &ev); 14397db96d56Sopenharmony_ci Py_END_ALLOW_THREADS 14407db96d56Sopenharmony_ci break; 14417db96d56Sopenharmony_ci case EPOLL_CTL_DEL: 14427db96d56Sopenharmony_ci /* In kernel versions before 2.6.9, the EPOLL_CTL_DEL 14437db96d56Sopenharmony_ci * operation required a non-NULL pointer in event, even 14447db96d56Sopenharmony_ci * though this argument is ignored. */ 14457db96d56Sopenharmony_ci Py_BEGIN_ALLOW_THREADS 14467db96d56Sopenharmony_ci result = epoll_ctl(epfd, op, fd, &ev); 14477db96d56Sopenharmony_ci Py_END_ALLOW_THREADS 14487db96d56Sopenharmony_ci break; 14497db96d56Sopenharmony_ci default: 14507db96d56Sopenharmony_ci result = -1; 14517db96d56Sopenharmony_ci errno = EINVAL; 14527db96d56Sopenharmony_ci } 14537db96d56Sopenharmony_ci 14547db96d56Sopenharmony_ci if (result < 0) { 14557db96d56Sopenharmony_ci PyErr_SetFromErrno(PyExc_OSError); 14567db96d56Sopenharmony_ci return NULL; 14577db96d56Sopenharmony_ci } 14587db96d56Sopenharmony_ci Py_RETURN_NONE; 14597db96d56Sopenharmony_ci} 14607db96d56Sopenharmony_ci 14617db96d56Sopenharmony_ci/*[clinic input] 14627db96d56Sopenharmony_ciselect.epoll.register 14637db96d56Sopenharmony_ci 14647db96d56Sopenharmony_ci fd: fildes 14657db96d56Sopenharmony_ci the target file descriptor of the operation 14667db96d56Sopenharmony_ci eventmask: unsigned_int(c_default="EPOLLIN | EPOLLPRI | EPOLLOUT", bitwise=True) = select.EPOLLIN | select.EPOLLPRI | select.EPOLLOUT 14677db96d56Sopenharmony_ci a bit set composed of the various EPOLL constants 14687db96d56Sopenharmony_ci 14697db96d56Sopenharmony_ciRegisters a new fd or raises an OSError if the fd is already registered. 14707db96d56Sopenharmony_ci 14717db96d56Sopenharmony_ciThe epoll interface supports all file descriptors that support poll. 14727db96d56Sopenharmony_ci[clinic start generated code]*/ 14737db96d56Sopenharmony_ci 14747db96d56Sopenharmony_cistatic PyObject * 14757db96d56Sopenharmony_ciselect_epoll_register_impl(pyEpoll_Object *self, int fd, 14767db96d56Sopenharmony_ci unsigned int eventmask) 14777db96d56Sopenharmony_ci/*[clinic end generated code: output=318e5e6386520599 input=a5071b71edfe3578]*/ 14787db96d56Sopenharmony_ci{ 14797db96d56Sopenharmony_ci return pyepoll_internal_ctl(self->epfd, EPOLL_CTL_ADD, fd, eventmask); 14807db96d56Sopenharmony_ci} 14817db96d56Sopenharmony_ci 14827db96d56Sopenharmony_ci/*[clinic input] 14837db96d56Sopenharmony_ciselect.epoll.modify 14847db96d56Sopenharmony_ci 14857db96d56Sopenharmony_ci fd: fildes 14867db96d56Sopenharmony_ci the target file descriptor of the operation 14877db96d56Sopenharmony_ci eventmask: unsigned_int(bitwise=True) 14887db96d56Sopenharmony_ci a bit set composed of the various EPOLL constants 14897db96d56Sopenharmony_ci 14907db96d56Sopenharmony_ciModify event mask for a registered file descriptor. 14917db96d56Sopenharmony_ci[clinic start generated code]*/ 14927db96d56Sopenharmony_ci 14937db96d56Sopenharmony_cistatic PyObject * 14947db96d56Sopenharmony_ciselect_epoll_modify_impl(pyEpoll_Object *self, int fd, 14957db96d56Sopenharmony_ci unsigned int eventmask) 14967db96d56Sopenharmony_ci/*[clinic end generated code: output=7e3447307cff6f65 input=88a83dac53a8c3da]*/ 14977db96d56Sopenharmony_ci{ 14987db96d56Sopenharmony_ci return pyepoll_internal_ctl(self->epfd, EPOLL_CTL_MOD, fd, eventmask); 14997db96d56Sopenharmony_ci} 15007db96d56Sopenharmony_ci 15017db96d56Sopenharmony_ci/*[clinic input] 15027db96d56Sopenharmony_ciselect.epoll.unregister 15037db96d56Sopenharmony_ci 15047db96d56Sopenharmony_ci fd: fildes 15057db96d56Sopenharmony_ci the target file descriptor of the operation 15067db96d56Sopenharmony_ci 15077db96d56Sopenharmony_ciRemove a registered file descriptor from the epoll object. 15087db96d56Sopenharmony_ci[clinic start generated code]*/ 15097db96d56Sopenharmony_ci 15107db96d56Sopenharmony_cistatic PyObject * 15117db96d56Sopenharmony_ciselect_epoll_unregister_impl(pyEpoll_Object *self, int fd) 15127db96d56Sopenharmony_ci/*[clinic end generated code: output=07c5dbd612a512d4 input=3093f68d3644743d]*/ 15137db96d56Sopenharmony_ci{ 15147db96d56Sopenharmony_ci return pyepoll_internal_ctl(self->epfd, EPOLL_CTL_DEL, fd, 0); 15157db96d56Sopenharmony_ci} 15167db96d56Sopenharmony_ci 15177db96d56Sopenharmony_ci/*[clinic input] 15187db96d56Sopenharmony_ciselect.epoll.poll 15197db96d56Sopenharmony_ci 15207db96d56Sopenharmony_ci timeout as timeout_obj: object = None 15217db96d56Sopenharmony_ci the maximum time to wait in seconds (as float); 15227db96d56Sopenharmony_ci a timeout of None or -1 makes poll wait indefinitely 15237db96d56Sopenharmony_ci maxevents: int = -1 15247db96d56Sopenharmony_ci the maximum number of events returned; -1 means no limit 15257db96d56Sopenharmony_ci 15267db96d56Sopenharmony_ciWait for events on the epoll file descriptor. 15277db96d56Sopenharmony_ci 15287db96d56Sopenharmony_ciReturns a list containing any descriptors that have events to report, 15297db96d56Sopenharmony_cias a list of (fd, events) 2-tuples. 15307db96d56Sopenharmony_ci[clinic start generated code]*/ 15317db96d56Sopenharmony_ci 15327db96d56Sopenharmony_cistatic PyObject * 15337db96d56Sopenharmony_ciselect_epoll_poll_impl(pyEpoll_Object *self, PyObject *timeout_obj, 15347db96d56Sopenharmony_ci int maxevents) 15357db96d56Sopenharmony_ci/*[clinic end generated code: output=e02d121a20246c6c input=33d34a5ea430fd5b]*/ 15367db96d56Sopenharmony_ci{ 15377db96d56Sopenharmony_ci int nfds, i; 15387db96d56Sopenharmony_ci PyObject *elist = NULL, *etuple = NULL; 15397db96d56Sopenharmony_ci struct epoll_event *evs = NULL; 15407db96d56Sopenharmony_ci _PyTime_t timeout = -1, ms = -1, deadline = 0; 15417db96d56Sopenharmony_ci 15427db96d56Sopenharmony_ci if (self->epfd < 0) 15437db96d56Sopenharmony_ci return pyepoll_err_closed(); 15447db96d56Sopenharmony_ci 15457db96d56Sopenharmony_ci if (timeout_obj != Py_None) { 15467db96d56Sopenharmony_ci /* epoll_wait() has a resolution of 1 millisecond, round towards 15477db96d56Sopenharmony_ci infinity to wait at least timeout seconds. */ 15487db96d56Sopenharmony_ci if (_PyTime_FromSecondsObject(&timeout, timeout_obj, 15497db96d56Sopenharmony_ci _PyTime_ROUND_TIMEOUT) < 0) { 15507db96d56Sopenharmony_ci if (PyErr_ExceptionMatches(PyExc_TypeError)) { 15517db96d56Sopenharmony_ci PyErr_SetString(PyExc_TypeError, 15527db96d56Sopenharmony_ci "timeout must be an integer or None"); 15537db96d56Sopenharmony_ci } 15547db96d56Sopenharmony_ci return NULL; 15557db96d56Sopenharmony_ci } 15567db96d56Sopenharmony_ci 15577db96d56Sopenharmony_ci ms = _PyTime_AsMilliseconds(timeout, _PyTime_ROUND_CEILING); 15587db96d56Sopenharmony_ci if (ms < INT_MIN || ms > INT_MAX) { 15597db96d56Sopenharmony_ci PyErr_SetString(PyExc_OverflowError, "timeout is too large"); 15607db96d56Sopenharmony_ci return NULL; 15617db96d56Sopenharmony_ci } 15627db96d56Sopenharmony_ci /* epoll_wait(2) treats all arbitrary negative numbers the same 15637db96d56Sopenharmony_ci for the timeout argument, but -1 is the documented way to block 15647db96d56Sopenharmony_ci indefinitely in the epoll_wait(2) documentation, so we set ms 15657db96d56Sopenharmony_ci to -1 if the value of ms is a negative number. 15667db96d56Sopenharmony_ci 15677db96d56Sopenharmony_ci Note that we didn't use INFTIM here since it's non-standard and 15687db96d56Sopenharmony_ci isn't available under Linux. */ 15697db96d56Sopenharmony_ci if (ms < 0) { 15707db96d56Sopenharmony_ci ms = -1; 15717db96d56Sopenharmony_ci } 15727db96d56Sopenharmony_ci 15737db96d56Sopenharmony_ci if (timeout >= 0) { 15747db96d56Sopenharmony_ci deadline = _PyDeadline_Init(timeout); 15757db96d56Sopenharmony_ci } 15767db96d56Sopenharmony_ci } 15777db96d56Sopenharmony_ci 15787db96d56Sopenharmony_ci if (maxevents == -1) { 15797db96d56Sopenharmony_ci maxevents = FD_SETSIZE-1; 15807db96d56Sopenharmony_ci } 15817db96d56Sopenharmony_ci else if (maxevents < 1) { 15827db96d56Sopenharmony_ci PyErr_Format(PyExc_ValueError, 15837db96d56Sopenharmony_ci "maxevents must be greater than 0, got %d", 15847db96d56Sopenharmony_ci maxevents); 15857db96d56Sopenharmony_ci return NULL; 15867db96d56Sopenharmony_ci } 15877db96d56Sopenharmony_ci 15887db96d56Sopenharmony_ci evs = PyMem_New(struct epoll_event, maxevents); 15897db96d56Sopenharmony_ci if (evs == NULL) { 15907db96d56Sopenharmony_ci PyErr_NoMemory(); 15917db96d56Sopenharmony_ci return NULL; 15927db96d56Sopenharmony_ci } 15937db96d56Sopenharmony_ci 15947db96d56Sopenharmony_ci do { 15957db96d56Sopenharmony_ci Py_BEGIN_ALLOW_THREADS 15967db96d56Sopenharmony_ci errno = 0; 15977db96d56Sopenharmony_ci nfds = epoll_wait(self->epfd, evs, maxevents, (int)ms); 15987db96d56Sopenharmony_ci Py_END_ALLOW_THREADS 15997db96d56Sopenharmony_ci 16007db96d56Sopenharmony_ci if (errno != EINTR) 16017db96d56Sopenharmony_ci break; 16027db96d56Sopenharmony_ci 16037db96d56Sopenharmony_ci /* poll() was interrupted by a signal */ 16047db96d56Sopenharmony_ci if (PyErr_CheckSignals()) 16057db96d56Sopenharmony_ci goto error; 16067db96d56Sopenharmony_ci 16077db96d56Sopenharmony_ci if (timeout >= 0) { 16087db96d56Sopenharmony_ci timeout = _PyDeadline_Get(deadline); 16097db96d56Sopenharmony_ci if (timeout < 0) { 16107db96d56Sopenharmony_ci nfds = 0; 16117db96d56Sopenharmony_ci break; 16127db96d56Sopenharmony_ci } 16137db96d56Sopenharmony_ci ms = _PyTime_AsMilliseconds(timeout, _PyTime_ROUND_CEILING); 16147db96d56Sopenharmony_ci /* retry epoll_wait() with the recomputed timeout */ 16157db96d56Sopenharmony_ci } 16167db96d56Sopenharmony_ci } while(1); 16177db96d56Sopenharmony_ci 16187db96d56Sopenharmony_ci if (nfds < 0) { 16197db96d56Sopenharmony_ci PyErr_SetFromErrno(PyExc_OSError); 16207db96d56Sopenharmony_ci goto error; 16217db96d56Sopenharmony_ci } 16227db96d56Sopenharmony_ci 16237db96d56Sopenharmony_ci elist = PyList_New(nfds); 16247db96d56Sopenharmony_ci if (elist == NULL) { 16257db96d56Sopenharmony_ci goto error; 16267db96d56Sopenharmony_ci } 16277db96d56Sopenharmony_ci 16287db96d56Sopenharmony_ci for (i = 0; i < nfds; i++) { 16297db96d56Sopenharmony_ci etuple = Py_BuildValue("iI", evs[i].data.fd, evs[i].events); 16307db96d56Sopenharmony_ci if (etuple == NULL) { 16317db96d56Sopenharmony_ci Py_CLEAR(elist); 16327db96d56Sopenharmony_ci goto error; 16337db96d56Sopenharmony_ci } 16347db96d56Sopenharmony_ci PyList_SET_ITEM(elist, i, etuple); 16357db96d56Sopenharmony_ci } 16367db96d56Sopenharmony_ci 16377db96d56Sopenharmony_ci error: 16387db96d56Sopenharmony_ci PyMem_Free(evs); 16397db96d56Sopenharmony_ci return elist; 16407db96d56Sopenharmony_ci} 16417db96d56Sopenharmony_ci 16427db96d56Sopenharmony_ci 16437db96d56Sopenharmony_ci/*[clinic input] 16447db96d56Sopenharmony_ciselect.epoll.__enter__ 16457db96d56Sopenharmony_ci 16467db96d56Sopenharmony_ci[clinic start generated code]*/ 16477db96d56Sopenharmony_ci 16487db96d56Sopenharmony_cistatic PyObject * 16497db96d56Sopenharmony_ciselect_epoll___enter___impl(pyEpoll_Object *self) 16507db96d56Sopenharmony_ci/*[clinic end generated code: output=ab45d433504db2a0 input=3c22568587efeadb]*/ 16517db96d56Sopenharmony_ci{ 16527db96d56Sopenharmony_ci if (self->epfd < 0) 16537db96d56Sopenharmony_ci return pyepoll_err_closed(); 16547db96d56Sopenharmony_ci 16557db96d56Sopenharmony_ci Py_INCREF(self); 16567db96d56Sopenharmony_ci return (PyObject *)self; 16577db96d56Sopenharmony_ci} 16587db96d56Sopenharmony_ci 16597db96d56Sopenharmony_ci/*[clinic input] 16607db96d56Sopenharmony_ciselect.epoll.__exit__ 16617db96d56Sopenharmony_ci 16627db96d56Sopenharmony_ci exc_type: object = None 16637db96d56Sopenharmony_ci exc_value: object = None 16647db96d56Sopenharmony_ci exc_tb: object = None 16657db96d56Sopenharmony_ci / 16667db96d56Sopenharmony_ci 16677db96d56Sopenharmony_ci[clinic start generated code]*/ 16687db96d56Sopenharmony_ci 16697db96d56Sopenharmony_cistatic PyObject * 16707db96d56Sopenharmony_ciselect_epoll___exit___impl(pyEpoll_Object *self, PyObject *exc_type, 16717db96d56Sopenharmony_ci PyObject *exc_value, PyObject *exc_tb) 16727db96d56Sopenharmony_ci/*[clinic end generated code: output=c480f38ce361748e input=7ae81a5a4c1a98d8]*/ 16737db96d56Sopenharmony_ci{ 16747db96d56Sopenharmony_ci _selectstate *state = _selectstate_by_type(Py_TYPE(self)); 16757db96d56Sopenharmony_ci return PyObject_CallMethodObjArgs((PyObject *)self, state->close, NULL); 16767db96d56Sopenharmony_ci} 16777db96d56Sopenharmony_ci 16787db96d56Sopenharmony_cistatic PyGetSetDef pyepoll_getsetlist[] = { 16797db96d56Sopenharmony_ci {"closed", (getter)pyepoll_get_closed, NULL, 16807db96d56Sopenharmony_ci "True if the epoll handler is closed"}, 16817db96d56Sopenharmony_ci {0}, 16827db96d56Sopenharmony_ci}; 16837db96d56Sopenharmony_ci 16847db96d56Sopenharmony_ciPyDoc_STRVAR(pyepoll_doc, 16857db96d56Sopenharmony_ci"select.epoll(sizehint=-1, flags=0)\n\ 16867db96d56Sopenharmony_ci\n\ 16877db96d56Sopenharmony_ciReturns an epolling object\n\ 16887db96d56Sopenharmony_ci\n\ 16897db96d56Sopenharmony_cisizehint must be a positive integer or -1 for the default size. The\n\ 16907db96d56Sopenharmony_cisizehint is used to optimize internal data structures. It doesn't limit\n\ 16917db96d56Sopenharmony_cithe maximum number of monitored events."); 16927db96d56Sopenharmony_ci 16937db96d56Sopenharmony_ci#endif /* HAVE_EPOLL */ 16947db96d56Sopenharmony_ci 16957db96d56Sopenharmony_ci#ifdef HAVE_KQUEUE 16967db96d56Sopenharmony_ci/* ************************************************************************** 16977db96d56Sopenharmony_ci * kqueue interface for BSD 16987db96d56Sopenharmony_ci * 16997db96d56Sopenharmony_ci * Copyright (c) 2000 Doug White, 2006 James Knight, 2007 Christian Heimes 17007db96d56Sopenharmony_ci * All rights reserved. 17017db96d56Sopenharmony_ci * 17027db96d56Sopenharmony_ci * Redistribution and use in source and binary forms, with or without 17037db96d56Sopenharmony_ci * modification, are permitted provided that the following conditions 17047db96d56Sopenharmony_ci * are met: 17057db96d56Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright 17067db96d56Sopenharmony_ci * notice, this list of conditions and the following disclaimer. 17077db96d56Sopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright 17087db96d56Sopenharmony_ci * notice, this list of conditions and the following disclaimer in the 17097db96d56Sopenharmony_ci * documentation and/or other materials provided with the distribution. 17107db96d56Sopenharmony_ci * 17117db96d56Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17127db96d56Sopenharmony_ci * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17137db96d56Sopenharmony_ci * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17147db96d56Sopenharmony_ci * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17157db96d56Sopenharmony_ci * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 17167db96d56Sopenharmony_ci * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 17177db96d56Sopenharmony_ci * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 17187db96d56Sopenharmony_ci * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 17197db96d56Sopenharmony_ci * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 17207db96d56Sopenharmony_ci * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 17217db96d56Sopenharmony_ci * SUCH DAMAGE. 17227db96d56Sopenharmony_ci */ 17237db96d56Sopenharmony_ci 17247db96d56Sopenharmony_ci#ifdef HAVE_SYS_EVENT_H 17257db96d56Sopenharmony_ci#include <sys/event.h> 17267db96d56Sopenharmony_ci#endif 17277db96d56Sopenharmony_ci 17287db96d56Sopenharmony_ciPyDoc_STRVAR(kqueue_event_doc, 17297db96d56Sopenharmony_ci"kevent(ident, filter=KQ_FILTER_READ, flags=KQ_EV_ADD, fflags=0, data=0, udata=0)\n\ 17307db96d56Sopenharmony_ci\n\ 17317db96d56Sopenharmony_ciThis object is the equivalent of the struct kevent for the C API.\n\ 17327db96d56Sopenharmony_ci\n\ 17337db96d56Sopenharmony_ciSee the kqueue manpage for more detailed information about the meaning\n\ 17347db96d56Sopenharmony_ciof the arguments.\n\ 17357db96d56Sopenharmony_ci\n\ 17367db96d56Sopenharmony_ciOne minor note: while you might hope that udata could store a\n\ 17377db96d56Sopenharmony_cireference to a python object, it cannot, because it is impossible to\n\ 17387db96d56Sopenharmony_cikeep a proper reference count of the object once it's passed into the\n\ 17397db96d56Sopenharmony_cikernel. Therefore, I have restricted it to only storing an integer. I\n\ 17407db96d56Sopenharmony_cirecommend ignoring it and simply using the 'ident' field to key off\n\ 17417db96d56Sopenharmony_ciof. You could also set up a dictionary on the python side to store a\n\ 17427db96d56Sopenharmony_ciudata->object mapping."); 17437db96d56Sopenharmony_ci 17447db96d56Sopenharmony_citypedef struct { 17457db96d56Sopenharmony_ci PyObject_HEAD 17467db96d56Sopenharmony_ci struct kevent e; 17477db96d56Sopenharmony_ci} kqueue_event_Object; 17487db96d56Sopenharmony_ci 17497db96d56Sopenharmony_ci#define kqueue_event_Check(op, state) (PyObject_TypeCheck((op), state->kqueue_event_Type)) 17507db96d56Sopenharmony_ci 17517db96d56Sopenharmony_citypedef struct { 17527db96d56Sopenharmony_ci PyObject_HEAD 17537db96d56Sopenharmony_ci SOCKET kqfd; /* kqueue control fd */ 17547db96d56Sopenharmony_ci} kqueue_queue_Object; 17557db96d56Sopenharmony_ci 17567db96d56Sopenharmony_ci#if (SIZEOF_UINTPTR_T != SIZEOF_VOID_P) 17577db96d56Sopenharmony_ci# error uintptr_t does not match void *! 17587db96d56Sopenharmony_ci#elif (SIZEOF_UINTPTR_T == SIZEOF_LONG_LONG) 17597db96d56Sopenharmony_ci# define T_UINTPTRT T_ULONGLONG 17607db96d56Sopenharmony_ci# define T_INTPTRT T_LONGLONG 17617db96d56Sopenharmony_ci# define UINTPTRT_FMT_UNIT "K" 17627db96d56Sopenharmony_ci# define INTPTRT_FMT_UNIT "L" 17637db96d56Sopenharmony_ci#elif (SIZEOF_UINTPTR_T == SIZEOF_LONG) 17647db96d56Sopenharmony_ci# define T_UINTPTRT T_ULONG 17657db96d56Sopenharmony_ci# define T_INTPTRT T_LONG 17667db96d56Sopenharmony_ci# define UINTPTRT_FMT_UNIT "k" 17677db96d56Sopenharmony_ci# define INTPTRT_FMT_UNIT "l" 17687db96d56Sopenharmony_ci#elif (SIZEOF_UINTPTR_T == SIZEOF_INT) 17697db96d56Sopenharmony_ci# define T_UINTPTRT T_UINT 17707db96d56Sopenharmony_ci# define T_INTPTRT T_INT 17717db96d56Sopenharmony_ci# define UINTPTRT_FMT_UNIT "I" 17727db96d56Sopenharmony_ci# define INTPTRT_FMT_UNIT "i" 17737db96d56Sopenharmony_ci#else 17747db96d56Sopenharmony_ci# error uintptr_t does not match int, long, or long long! 17757db96d56Sopenharmony_ci#endif 17767db96d56Sopenharmony_ci 17777db96d56Sopenharmony_ci#if SIZEOF_LONG_LONG == 8 17787db96d56Sopenharmony_ci# define T_INT64 T_LONGLONG 17797db96d56Sopenharmony_ci# define INT64_FMT_UNIT "L" 17807db96d56Sopenharmony_ci#elif SIZEOF_LONG == 8 17817db96d56Sopenharmony_ci# define T_INT64 T_LONG 17827db96d56Sopenharmony_ci# define INT64_FMT_UNIT "l" 17837db96d56Sopenharmony_ci#elif SIZEOF_INT == 8 17847db96d56Sopenharmony_ci# define T_INT64 T_INT 17857db96d56Sopenharmony_ci# define INT64_FMT_UNIT "i" 17867db96d56Sopenharmony_ci#else 17877db96d56Sopenharmony_ci# define INT64_FMT_UNIT "_" 17887db96d56Sopenharmony_ci#endif 17897db96d56Sopenharmony_ci 17907db96d56Sopenharmony_ci#if SIZEOF_LONG_LONG == 4 17917db96d56Sopenharmony_ci# define T_UINT32 T_ULONGLONG 17927db96d56Sopenharmony_ci# define UINT32_FMT_UNIT "K" 17937db96d56Sopenharmony_ci#elif SIZEOF_LONG == 4 17947db96d56Sopenharmony_ci# define T_UINT32 T_ULONG 17957db96d56Sopenharmony_ci# define UINT32_FMT_UNIT "k" 17967db96d56Sopenharmony_ci#elif SIZEOF_INT == 4 17977db96d56Sopenharmony_ci# define T_UINT32 T_UINT 17987db96d56Sopenharmony_ci# define UINT32_FMT_UNIT "I" 17997db96d56Sopenharmony_ci#else 18007db96d56Sopenharmony_ci# define UINT32_FMT_UNIT "_" 18017db96d56Sopenharmony_ci#endif 18027db96d56Sopenharmony_ci 18037db96d56Sopenharmony_ci/* 18047db96d56Sopenharmony_ci * kevent is not standard and its members vary across BSDs. 18057db96d56Sopenharmony_ci */ 18067db96d56Sopenharmony_ci#ifdef __NetBSD__ 18077db96d56Sopenharmony_ci# define FILTER_TYPE T_UINT32 18087db96d56Sopenharmony_ci# define FILTER_FMT_UNIT UINT32_FMT_UNIT 18097db96d56Sopenharmony_ci# define FLAGS_TYPE T_UINT32 18107db96d56Sopenharmony_ci# define FLAGS_FMT_UNIT UINT32_FMT_UNIT 18117db96d56Sopenharmony_ci# define FFLAGS_TYPE T_UINT32 18127db96d56Sopenharmony_ci# define FFLAGS_FMT_UNIT UINT32_FMT_UNIT 18137db96d56Sopenharmony_ci#else 18147db96d56Sopenharmony_ci# define FILTER_TYPE T_SHORT 18157db96d56Sopenharmony_ci# define FILTER_FMT_UNIT "h" 18167db96d56Sopenharmony_ci# define FLAGS_TYPE T_USHORT 18177db96d56Sopenharmony_ci# define FLAGS_FMT_UNIT "H" 18187db96d56Sopenharmony_ci# define FFLAGS_TYPE T_UINT 18197db96d56Sopenharmony_ci# define FFLAGS_FMT_UNIT "I" 18207db96d56Sopenharmony_ci#endif 18217db96d56Sopenharmony_ci 18227db96d56Sopenharmony_ci#if defined(__NetBSD__) || defined(__OpenBSD__) 18237db96d56Sopenharmony_ci# define DATA_TYPE T_INT64 18247db96d56Sopenharmony_ci# define DATA_FMT_UNIT INT64_FMT_UNIT 18257db96d56Sopenharmony_ci#else 18267db96d56Sopenharmony_ci# define DATA_TYPE T_INTPTRT 18277db96d56Sopenharmony_ci# define DATA_FMT_UNIT INTPTRT_FMT_UNIT 18287db96d56Sopenharmony_ci#endif 18297db96d56Sopenharmony_ci 18307db96d56Sopenharmony_ci/* Unfortunately, we can't store python objects in udata, because 18317db96d56Sopenharmony_ci * kevents in the kernel can be removed without warning, which would 18327db96d56Sopenharmony_ci * forever lose the refcount on the object stored with it. 18337db96d56Sopenharmony_ci */ 18347db96d56Sopenharmony_ci 18357db96d56Sopenharmony_ci#define KQ_OFF(x) offsetof(kqueue_event_Object, x) 18367db96d56Sopenharmony_cistatic struct PyMemberDef kqueue_event_members[] = { 18377db96d56Sopenharmony_ci {"ident", T_UINTPTRT, KQ_OFF(e.ident)}, 18387db96d56Sopenharmony_ci {"filter", FILTER_TYPE, KQ_OFF(e.filter)}, 18397db96d56Sopenharmony_ci {"flags", FLAGS_TYPE, KQ_OFF(e.flags)}, 18407db96d56Sopenharmony_ci {"fflags", T_UINT, KQ_OFF(e.fflags)}, 18417db96d56Sopenharmony_ci {"data", DATA_TYPE, KQ_OFF(e.data)}, 18427db96d56Sopenharmony_ci {"udata", T_UINTPTRT, KQ_OFF(e.udata)}, 18437db96d56Sopenharmony_ci {NULL} /* Sentinel */ 18447db96d56Sopenharmony_ci}; 18457db96d56Sopenharmony_ci#undef KQ_OFF 18467db96d56Sopenharmony_ci 18477db96d56Sopenharmony_cistatic PyObject * 18487db96d56Sopenharmony_ci 18497db96d56Sopenharmony_cikqueue_event_repr(kqueue_event_Object *s) 18507db96d56Sopenharmony_ci{ 18517db96d56Sopenharmony_ci char buf[1024]; 18527db96d56Sopenharmony_ci PyOS_snprintf( 18537db96d56Sopenharmony_ci buf, sizeof(buf), 18547db96d56Sopenharmony_ci "<select.kevent ident=%zu filter=%d flags=0x%x fflags=0x%x " 18557db96d56Sopenharmony_ci "data=0x%llx udata=%p>", 18567db96d56Sopenharmony_ci (size_t)(s->e.ident), (int)s->e.filter, (unsigned int)s->e.flags, 18577db96d56Sopenharmony_ci (unsigned int)s->e.fflags, (long long)(s->e.data), (void *)s->e.udata); 18587db96d56Sopenharmony_ci return PyUnicode_FromString(buf); 18597db96d56Sopenharmony_ci} 18607db96d56Sopenharmony_ci 18617db96d56Sopenharmony_cistatic int 18627db96d56Sopenharmony_cikqueue_event_init(kqueue_event_Object *self, PyObject *args, PyObject *kwds) 18637db96d56Sopenharmony_ci{ 18647db96d56Sopenharmony_ci PyObject *pfd; 18657db96d56Sopenharmony_ci static char *kwlist[] = {"ident", "filter", "flags", "fflags", 18667db96d56Sopenharmony_ci "data", "udata", NULL}; 18677db96d56Sopenharmony_ci static const char fmt[] = "O|" 18687db96d56Sopenharmony_ci FILTER_FMT_UNIT FLAGS_FMT_UNIT FFLAGS_FMT_UNIT DATA_FMT_UNIT 18697db96d56Sopenharmony_ci UINTPTRT_FMT_UNIT ":kevent"; 18707db96d56Sopenharmony_ci 18717db96d56Sopenharmony_ci EV_SET(&(self->e), 0, EVFILT_READ, EV_ADD, 0, 0, 0); /* defaults */ 18727db96d56Sopenharmony_ci 18737db96d56Sopenharmony_ci if (!PyArg_ParseTupleAndKeywords(args, kwds, fmt, kwlist, 18747db96d56Sopenharmony_ci &pfd, &(self->e.filter), &(self->e.flags), 18757db96d56Sopenharmony_ci &(self->e.fflags), &(self->e.data), &(self->e.udata))) { 18767db96d56Sopenharmony_ci return -1; 18777db96d56Sopenharmony_ci } 18787db96d56Sopenharmony_ci 18797db96d56Sopenharmony_ci if (PyLong_Check(pfd)) { 18807db96d56Sopenharmony_ci self->e.ident = PyLong_AsSize_t(pfd); 18817db96d56Sopenharmony_ci } 18827db96d56Sopenharmony_ci else { 18837db96d56Sopenharmony_ci self->e.ident = PyObject_AsFileDescriptor(pfd); 18847db96d56Sopenharmony_ci } 18857db96d56Sopenharmony_ci if (PyErr_Occurred()) { 18867db96d56Sopenharmony_ci return -1; 18877db96d56Sopenharmony_ci } 18887db96d56Sopenharmony_ci return 0; 18897db96d56Sopenharmony_ci} 18907db96d56Sopenharmony_ci 18917db96d56Sopenharmony_cistatic PyObject * 18927db96d56Sopenharmony_cikqueue_event_richcompare(kqueue_event_Object *s, kqueue_event_Object *o, 18937db96d56Sopenharmony_ci int op) 18947db96d56Sopenharmony_ci{ 18957db96d56Sopenharmony_ci int result; 18967db96d56Sopenharmony_ci _selectstate *state = _selectstate_by_type(Py_TYPE(s)); 18977db96d56Sopenharmony_ci 18987db96d56Sopenharmony_ci if (!kqueue_event_Check(o, state)) { 18997db96d56Sopenharmony_ci Py_RETURN_NOTIMPLEMENTED; 19007db96d56Sopenharmony_ci } 19017db96d56Sopenharmony_ci 19027db96d56Sopenharmony_ci#define CMP(a, b) ((a) != (b)) ? ((a) < (b) ? -1 : 1) 19037db96d56Sopenharmony_ci result = CMP(s->e.ident, o->e.ident) 19047db96d56Sopenharmony_ci : CMP(s->e.filter, o->e.filter) 19057db96d56Sopenharmony_ci : CMP(s->e.flags, o->e.flags) 19067db96d56Sopenharmony_ci : CMP(s->e.fflags, o->e.fflags) 19077db96d56Sopenharmony_ci : CMP(s->e.data, o->e.data) 19087db96d56Sopenharmony_ci : CMP((intptr_t)s->e.udata, (intptr_t)o->e.udata) 19097db96d56Sopenharmony_ci : 0; 19107db96d56Sopenharmony_ci#undef CMP 19117db96d56Sopenharmony_ci 19127db96d56Sopenharmony_ci Py_RETURN_RICHCOMPARE(result, 0, op); 19137db96d56Sopenharmony_ci} 19147db96d56Sopenharmony_ci 19157db96d56Sopenharmony_cistatic PyType_Slot kqueue_event_Type_slots[] = { 19167db96d56Sopenharmony_ci {Py_tp_doc, (void*)kqueue_event_doc}, 19177db96d56Sopenharmony_ci {Py_tp_init, kqueue_event_init}, 19187db96d56Sopenharmony_ci {Py_tp_members, kqueue_event_members}, 19197db96d56Sopenharmony_ci {Py_tp_new, PyType_GenericNew}, 19207db96d56Sopenharmony_ci {Py_tp_repr, kqueue_event_repr}, 19217db96d56Sopenharmony_ci {Py_tp_richcompare, kqueue_event_richcompare}, 19227db96d56Sopenharmony_ci {0, 0}, 19237db96d56Sopenharmony_ci}; 19247db96d56Sopenharmony_ci 19257db96d56Sopenharmony_cistatic PyType_Spec kqueue_event_Type_spec = { 19267db96d56Sopenharmony_ci "select.kevent", 19277db96d56Sopenharmony_ci sizeof(kqueue_event_Object), 19287db96d56Sopenharmony_ci 0, 19297db96d56Sopenharmony_ci Py_TPFLAGS_DEFAULT, 19307db96d56Sopenharmony_ci kqueue_event_Type_slots 19317db96d56Sopenharmony_ci}; 19327db96d56Sopenharmony_ci 19337db96d56Sopenharmony_cistatic PyObject * 19347db96d56Sopenharmony_cikqueue_queue_err_closed(void) 19357db96d56Sopenharmony_ci{ 19367db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, "I/O operation on closed kqueue object"); 19377db96d56Sopenharmony_ci return NULL; 19387db96d56Sopenharmony_ci} 19397db96d56Sopenharmony_ci 19407db96d56Sopenharmony_cistatic int 19417db96d56Sopenharmony_cikqueue_queue_internal_close(kqueue_queue_Object *self) 19427db96d56Sopenharmony_ci{ 19437db96d56Sopenharmony_ci int save_errno = 0; 19447db96d56Sopenharmony_ci if (self->kqfd >= 0) { 19457db96d56Sopenharmony_ci int kqfd = self->kqfd; 19467db96d56Sopenharmony_ci self->kqfd = -1; 19477db96d56Sopenharmony_ci Py_BEGIN_ALLOW_THREADS 19487db96d56Sopenharmony_ci if (close(kqfd) < 0) 19497db96d56Sopenharmony_ci save_errno = errno; 19507db96d56Sopenharmony_ci Py_END_ALLOW_THREADS 19517db96d56Sopenharmony_ci } 19527db96d56Sopenharmony_ci return save_errno; 19537db96d56Sopenharmony_ci} 19547db96d56Sopenharmony_ci 19557db96d56Sopenharmony_cistatic PyObject * 19567db96d56Sopenharmony_cinewKqueue_Object(PyTypeObject *type, SOCKET fd) 19577db96d56Sopenharmony_ci{ 19587db96d56Sopenharmony_ci kqueue_queue_Object *self; 19597db96d56Sopenharmony_ci assert(type != NULL); 19607db96d56Sopenharmony_ci allocfunc queue_alloc = PyType_GetSlot(type, Py_tp_alloc); 19617db96d56Sopenharmony_ci assert(queue_alloc != NULL); 19627db96d56Sopenharmony_ci self = (kqueue_queue_Object *) queue_alloc(type, 0); 19637db96d56Sopenharmony_ci if (self == NULL) { 19647db96d56Sopenharmony_ci return NULL; 19657db96d56Sopenharmony_ci } 19667db96d56Sopenharmony_ci 19677db96d56Sopenharmony_ci if (fd == -1) { 19687db96d56Sopenharmony_ci Py_BEGIN_ALLOW_THREADS 19697db96d56Sopenharmony_ci self->kqfd = kqueue(); 19707db96d56Sopenharmony_ci Py_END_ALLOW_THREADS 19717db96d56Sopenharmony_ci } 19727db96d56Sopenharmony_ci else { 19737db96d56Sopenharmony_ci self->kqfd = fd; 19747db96d56Sopenharmony_ci } 19757db96d56Sopenharmony_ci if (self->kqfd < 0) { 19767db96d56Sopenharmony_ci Py_DECREF(self); 19777db96d56Sopenharmony_ci PyErr_SetFromErrno(PyExc_OSError); 19787db96d56Sopenharmony_ci return NULL; 19797db96d56Sopenharmony_ci } 19807db96d56Sopenharmony_ci 19817db96d56Sopenharmony_ci if (fd == -1) { 19827db96d56Sopenharmony_ci if (_Py_set_inheritable(self->kqfd, 0, NULL) < 0) { 19837db96d56Sopenharmony_ci Py_DECREF(self); 19847db96d56Sopenharmony_ci return NULL; 19857db96d56Sopenharmony_ci } 19867db96d56Sopenharmony_ci } 19877db96d56Sopenharmony_ci return (PyObject *)self; 19887db96d56Sopenharmony_ci} 19897db96d56Sopenharmony_ci 19907db96d56Sopenharmony_ci/*[clinic input] 19917db96d56Sopenharmony_ci@classmethod 19927db96d56Sopenharmony_ciselect.kqueue.__new__ 19937db96d56Sopenharmony_ci 19947db96d56Sopenharmony_ciKqueue syscall wrapper. 19957db96d56Sopenharmony_ci 19967db96d56Sopenharmony_ciFor example, to start watching a socket for input: 19977db96d56Sopenharmony_ci>>> kq = kqueue() 19987db96d56Sopenharmony_ci>>> sock = socket() 19997db96d56Sopenharmony_ci>>> sock.connect((host, port)) 20007db96d56Sopenharmony_ci>>> kq.control([kevent(sock, KQ_FILTER_WRITE, KQ_EV_ADD)], 0) 20017db96d56Sopenharmony_ci 20027db96d56Sopenharmony_ciTo wait one second for it to become writeable: 20037db96d56Sopenharmony_ci>>> kq.control(None, 1, 1000) 20047db96d56Sopenharmony_ci 20057db96d56Sopenharmony_ciTo stop listening: 20067db96d56Sopenharmony_ci>>> kq.control([kevent(sock, KQ_FILTER_WRITE, KQ_EV_DELETE)], 0) 20077db96d56Sopenharmony_ci[clinic start generated code]*/ 20087db96d56Sopenharmony_ci 20097db96d56Sopenharmony_cistatic PyObject * 20107db96d56Sopenharmony_ciselect_kqueue_impl(PyTypeObject *type) 20117db96d56Sopenharmony_ci/*[clinic end generated code: output=e0ff89f154d56236 input=cf625e49218366e8]*/ 20127db96d56Sopenharmony_ci{ 20137db96d56Sopenharmony_ci return newKqueue_Object(type, -1); 20147db96d56Sopenharmony_ci} 20157db96d56Sopenharmony_ci 20167db96d56Sopenharmony_cistatic void 20177db96d56Sopenharmony_cikqueue_queue_dealloc(kqueue_queue_Object *self) 20187db96d56Sopenharmony_ci{ 20197db96d56Sopenharmony_ci PyTypeObject* type = Py_TYPE(self); 20207db96d56Sopenharmony_ci kqueue_queue_internal_close(self); 20217db96d56Sopenharmony_ci freefunc kqueue_free = PyType_GetSlot(type, Py_tp_free); 20227db96d56Sopenharmony_ci kqueue_free((PyObject *)self); 20237db96d56Sopenharmony_ci Py_DECREF((PyObject *)type); 20247db96d56Sopenharmony_ci} 20257db96d56Sopenharmony_ci 20267db96d56Sopenharmony_ci/*[clinic input] 20277db96d56Sopenharmony_ciselect.kqueue.close 20287db96d56Sopenharmony_ci 20297db96d56Sopenharmony_ciClose the kqueue control file descriptor. 20307db96d56Sopenharmony_ci 20317db96d56Sopenharmony_ciFurther operations on the kqueue object will raise an exception. 20327db96d56Sopenharmony_ci[clinic start generated code]*/ 20337db96d56Sopenharmony_ci 20347db96d56Sopenharmony_cistatic PyObject * 20357db96d56Sopenharmony_ciselect_kqueue_close_impl(kqueue_queue_Object *self) 20367db96d56Sopenharmony_ci/*[clinic end generated code: output=d1c7df0b407a4bc1 input=0b12d95430e0634c]*/ 20377db96d56Sopenharmony_ci{ 20387db96d56Sopenharmony_ci errno = kqueue_queue_internal_close(self); 20397db96d56Sopenharmony_ci if (errno < 0) { 20407db96d56Sopenharmony_ci PyErr_SetFromErrno(PyExc_OSError); 20417db96d56Sopenharmony_ci return NULL; 20427db96d56Sopenharmony_ci } 20437db96d56Sopenharmony_ci Py_RETURN_NONE; 20447db96d56Sopenharmony_ci} 20457db96d56Sopenharmony_ci 20467db96d56Sopenharmony_cistatic PyObject* 20477db96d56Sopenharmony_cikqueue_queue_get_closed(kqueue_queue_Object *self, void *Py_UNUSED(ignored)) 20487db96d56Sopenharmony_ci{ 20497db96d56Sopenharmony_ci if (self->kqfd < 0) 20507db96d56Sopenharmony_ci Py_RETURN_TRUE; 20517db96d56Sopenharmony_ci else 20527db96d56Sopenharmony_ci Py_RETURN_FALSE; 20537db96d56Sopenharmony_ci} 20547db96d56Sopenharmony_ci 20557db96d56Sopenharmony_ci/*[clinic input] 20567db96d56Sopenharmony_ciselect.kqueue.fileno 20577db96d56Sopenharmony_ci 20587db96d56Sopenharmony_ciReturn the kqueue control file descriptor. 20597db96d56Sopenharmony_ci[clinic start generated code]*/ 20607db96d56Sopenharmony_ci 20617db96d56Sopenharmony_cistatic PyObject * 20627db96d56Sopenharmony_ciselect_kqueue_fileno_impl(kqueue_queue_Object *self) 20637db96d56Sopenharmony_ci/*[clinic end generated code: output=716f46112a4f6e5c input=41911c539ca2b0ca]*/ 20647db96d56Sopenharmony_ci{ 20657db96d56Sopenharmony_ci if (self->kqfd < 0) 20667db96d56Sopenharmony_ci return kqueue_queue_err_closed(); 20677db96d56Sopenharmony_ci return PyLong_FromLong(self->kqfd); 20687db96d56Sopenharmony_ci} 20697db96d56Sopenharmony_ci 20707db96d56Sopenharmony_ci/*[clinic input] 20717db96d56Sopenharmony_ci@classmethod 20727db96d56Sopenharmony_ciselect.kqueue.fromfd 20737db96d56Sopenharmony_ci 20747db96d56Sopenharmony_ci fd: int 20757db96d56Sopenharmony_ci / 20767db96d56Sopenharmony_ci 20777db96d56Sopenharmony_ciCreate a kqueue object from a given control fd. 20787db96d56Sopenharmony_ci[clinic start generated code]*/ 20797db96d56Sopenharmony_ci 20807db96d56Sopenharmony_cistatic PyObject * 20817db96d56Sopenharmony_ciselect_kqueue_fromfd_impl(PyTypeObject *type, int fd) 20827db96d56Sopenharmony_ci/*[clinic end generated code: output=d02c3c7dc538a653 input=f6172a48ca4ecdd0]*/ 20837db96d56Sopenharmony_ci{ 20847db96d56Sopenharmony_ci SOCKET s_fd = (SOCKET)fd; 20857db96d56Sopenharmony_ci 20867db96d56Sopenharmony_ci return newKqueue_Object(type, s_fd); 20877db96d56Sopenharmony_ci} 20887db96d56Sopenharmony_ci 20897db96d56Sopenharmony_ci/*[clinic input] 20907db96d56Sopenharmony_ciselect.kqueue.control 20917db96d56Sopenharmony_ci 20927db96d56Sopenharmony_ci changelist: object 20937db96d56Sopenharmony_ci Must be an iterable of kevent objects describing the changes to be made 20947db96d56Sopenharmony_ci to the kernel's watch list or None. 20957db96d56Sopenharmony_ci maxevents: int 20967db96d56Sopenharmony_ci The maximum number of events that the kernel will return. 20977db96d56Sopenharmony_ci timeout as otimeout: object = None 20987db96d56Sopenharmony_ci The maximum time to wait in seconds, or else None to wait forever. 20997db96d56Sopenharmony_ci This accepts floats for smaller timeouts, too. 21007db96d56Sopenharmony_ci / 21017db96d56Sopenharmony_ci 21027db96d56Sopenharmony_ciCalls the kernel kevent function. 21037db96d56Sopenharmony_ci[clinic start generated code]*/ 21047db96d56Sopenharmony_ci 21057db96d56Sopenharmony_cistatic PyObject * 21067db96d56Sopenharmony_ciselect_kqueue_control_impl(kqueue_queue_Object *self, PyObject *changelist, 21077db96d56Sopenharmony_ci int maxevents, PyObject *otimeout) 21087db96d56Sopenharmony_ci/*[clinic end generated code: output=81324ff5130db7ae input=59c4e30811209c47]*/ 21097db96d56Sopenharmony_ci{ 21107db96d56Sopenharmony_ci int gotevents = 0; 21117db96d56Sopenharmony_ci int nchanges = 0; 21127db96d56Sopenharmony_ci int i = 0; 21137db96d56Sopenharmony_ci PyObject *seq = NULL, *ei = NULL; 21147db96d56Sopenharmony_ci PyObject *result = NULL; 21157db96d56Sopenharmony_ci struct kevent *evl = NULL; 21167db96d56Sopenharmony_ci struct kevent *chl = NULL; 21177db96d56Sopenharmony_ci struct timespec timeoutspec; 21187db96d56Sopenharmony_ci struct timespec *ptimeoutspec; 21197db96d56Sopenharmony_ci _PyTime_t timeout, deadline = 0; 21207db96d56Sopenharmony_ci _selectstate *state = _selectstate_by_type(Py_TYPE(self)); 21217db96d56Sopenharmony_ci 21227db96d56Sopenharmony_ci if (self->kqfd < 0) 21237db96d56Sopenharmony_ci return kqueue_queue_err_closed(); 21247db96d56Sopenharmony_ci 21257db96d56Sopenharmony_ci if (maxevents < 0) { 21267db96d56Sopenharmony_ci PyErr_Format(PyExc_ValueError, 21277db96d56Sopenharmony_ci "Length of eventlist must be 0 or positive, got %d", 21287db96d56Sopenharmony_ci maxevents); 21297db96d56Sopenharmony_ci return NULL; 21307db96d56Sopenharmony_ci } 21317db96d56Sopenharmony_ci 21327db96d56Sopenharmony_ci if (otimeout == Py_None) { 21337db96d56Sopenharmony_ci ptimeoutspec = NULL; 21347db96d56Sopenharmony_ci } 21357db96d56Sopenharmony_ci else { 21367db96d56Sopenharmony_ci if (_PyTime_FromSecondsObject(&timeout, 21377db96d56Sopenharmony_ci otimeout, _PyTime_ROUND_TIMEOUT) < 0) { 21387db96d56Sopenharmony_ci PyErr_Format(PyExc_TypeError, 21397db96d56Sopenharmony_ci "timeout argument must be a number " 21407db96d56Sopenharmony_ci "or None, got %.200s", 21417db96d56Sopenharmony_ci _PyType_Name(Py_TYPE(otimeout))); 21427db96d56Sopenharmony_ci return NULL; 21437db96d56Sopenharmony_ci } 21447db96d56Sopenharmony_ci 21457db96d56Sopenharmony_ci if (_PyTime_AsTimespec(timeout, &timeoutspec) == -1) 21467db96d56Sopenharmony_ci return NULL; 21477db96d56Sopenharmony_ci 21487db96d56Sopenharmony_ci if (timeoutspec.tv_sec < 0) { 21497db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, 21507db96d56Sopenharmony_ci "timeout must be positive or None"); 21517db96d56Sopenharmony_ci return NULL; 21527db96d56Sopenharmony_ci } 21537db96d56Sopenharmony_ci ptimeoutspec = &timeoutspec; 21547db96d56Sopenharmony_ci } 21557db96d56Sopenharmony_ci 21567db96d56Sopenharmony_ci if (changelist != Py_None) { 21577db96d56Sopenharmony_ci seq = PySequence_Fast(changelist, "changelist is not iterable"); 21587db96d56Sopenharmony_ci if (seq == NULL) { 21597db96d56Sopenharmony_ci return NULL; 21607db96d56Sopenharmony_ci } 21617db96d56Sopenharmony_ci if (PySequence_Fast_GET_SIZE(seq) > INT_MAX) { 21627db96d56Sopenharmony_ci PyErr_SetString(PyExc_OverflowError, 21637db96d56Sopenharmony_ci "changelist is too long"); 21647db96d56Sopenharmony_ci goto error; 21657db96d56Sopenharmony_ci } 21667db96d56Sopenharmony_ci nchanges = (int)PySequence_Fast_GET_SIZE(seq); 21677db96d56Sopenharmony_ci 21687db96d56Sopenharmony_ci chl = PyMem_New(struct kevent, nchanges); 21697db96d56Sopenharmony_ci if (chl == NULL) { 21707db96d56Sopenharmony_ci PyErr_NoMemory(); 21717db96d56Sopenharmony_ci goto error; 21727db96d56Sopenharmony_ci } 21737db96d56Sopenharmony_ci _selectstate *state = _selectstate_by_type(Py_TYPE(self)); 21747db96d56Sopenharmony_ci for (i = 0; i < nchanges; ++i) { 21757db96d56Sopenharmony_ci ei = PySequence_Fast_GET_ITEM(seq, i); 21767db96d56Sopenharmony_ci if (!kqueue_event_Check(ei, state)) { 21777db96d56Sopenharmony_ci PyErr_SetString(PyExc_TypeError, 21787db96d56Sopenharmony_ci "changelist must be an iterable of " 21797db96d56Sopenharmony_ci "select.kevent objects"); 21807db96d56Sopenharmony_ci goto error; 21817db96d56Sopenharmony_ci } 21827db96d56Sopenharmony_ci chl[i] = ((kqueue_event_Object *)ei)->e; 21837db96d56Sopenharmony_ci } 21847db96d56Sopenharmony_ci Py_CLEAR(seq); 21857db96d56Sopenharmony_ci } 21867db96d56Sopenharmony_ci 21877db96d56Sopenharmony_ci /* event list */ 21887db96d56Sopenharmony_ci if (maxevents) { 21897db96d56Sopenharmony_ci evl = PyMem_New(struct kevent, maxevents); 21907db96d56Sopenharmony_ci if (evl == NULL) { 21917db96d56Sopenharmony_ci PyErr_NoMemory(); 21927db96d56Sopenharmony_ci goto error; 21937db96d56Sopenharmony_ci } 21947db96d56Sopenharmony_ci } 21957db96d56Sopenharmony_ci 21967db96d56Sopenharmony_ci if (ptimeoutspec) { 21977db96d56Sopenharmony_ci deadline = _PyDeadline_Init(timeout); 21987db96d56Sopenharmony_ci } 21997db96d56Sopenharmony_ci 22007db96d56Sopenharmony_ci do { 22017db96d56Sopenharmony_ci Py_BEGIN_ALLOW_THREADS 22027db96d56Sopenharmony_ci errno = 0; 22037db96d56Sopenharmony_ci gotevents = kevent(self->kqfd, chl, nchanges, 22047db96d56Sopenharmony_ci evl, maxevents, ptimeoutspec); 22057db96d56Sopenharmony_ci Py_END_ALLOW_THREADS 22067db96d56Sopenharmony_ci 22077db96d56Sopenharmony_ci if (errno != EINTR) 22087db96d56Sopenharmony_ci break; 22097db96d56Sopenharmony_ci 22107db96d56Sopenharmony_ci /* kevent() was interrupted by a signal */ 22117db96d56Sopenharmony_ci if (PyErr_CheckSignals()) 22127db96d56Sopenharmony_ci goto error; 22137db96d56Sopenharmony_ci 22147db96d56Sopenharmony_ci if (ptimeoutspec) { 22157db96d56Sopenharmony_ci timeout = _PyDeadline_Get(deadline); 22167db96d56Sopenharmony_ci if (timeout < 0) { 22177db96d56Sopenharmony_ci gotevents = 0; 22187db96d56Sopenharmony_ci break; 22197db96d56Sopenharmony_ci } 22207db96d56Sopenharmony_ci if (_PyTime_AsTimespec(timeout, &timeoutspec) == -1) 22217db96d56Sopenharmony_ci goto error; 22227db96d56Sopenharmony_ci /* retry kevent() with the recomputed timeout */ 22237db96d56Sopenharmony_ci } 22247db96d56Sopenharmony_ci } while (1); 22257db96d56Sopenharmony_ci 22267db96d56Sopenharmony_ci if (gotevents == -1) { 22277db96d56Sopenharmony_ci PyErr_SetFromErrno(PyExc_OSError); 22287db96d56Sopenharmony_ci goto error; 22297db96d56Sopenharmony_ci } 22307db96d56Sopenharmony_ci 22317db96d56Sopenharmony_ci result = PyList_New(gotevents); 22327db96d56Sopenharmony_ci if (result == NULL) { 22337db96d56Sopenharmony_ci goto error; 22347db96d56Sopenharmony_ci } 22357db96d56Sopenharmony_ci 22367db96d56Sopenharmony_ci for (i = 0; i < gotevents; i++) { 22377db96d56Sopenharmony_ci kqueue_event_Object *ch; 22387db96d56Sopenharmony_ci 22397db96d56Sopenharmony_ci ch = PyObject_New(kqueue_event_Object, state->kqueue_event_Type); 22407db96d56Sopenharmony_ci if (ch == NULL) { 22417db96d56Sopenharmony_ci goto error; 22427db96d56Sopenharmony_ci } 22437db96d56Sopenharmony_ci ch->e = evl[i]; 22447db96d56Sopenharmony_ci PyList_SET_ITEM(result, i, (PyObject *)ch); 22457db96d56Sopenharmony_ci } 22467db96d56Sopenharmony_ci PyMem_Free(chl); 22477db96d56Sopenharmony_ci PyMem_Free(evl); 22487db96d56Sopenharmony_ci return result; 22497db96d56Sopenharmony_ci 22507db96d56Sopenharmony_ci error: 22517db96d56Sopenharmony_ci PyMem_Free(chl); 22527db96d56Sopenharmony_ci PyMem_Free(evl); 22537db96d56Sopenharmony_ci Py_XDECREF(result); 22547db96d56Sopenharmony_ci Py_XDECREF(seq); 22557db96d56Sopenharmony_ci return NULL; 22567db96d56Sopenharmony_ci} 22577db96d56Sopenharmony_ci 22587db96d56Sopenharmony_cistatic PyGetSetDef kqueue_queue_getsetlist[] = { 22597db96d56Sopenharmony_ci {"closed", (getter)kqueue_queue_get_closed, NULL, 22607db96d56Sopenharmony_ci "True if the kqueue handler is closed"}, 22617db96d56Sopenharmony_ci {0}, 22627db96d56Sopenharmony_ci}; 22637db96d56Sopenharmony_ci 22647db96d56Sopenharmony_ci#endif /* HAVE_KQUEUE */ 22657db96d56Sopenharmony_ci 22667db96d56Sopenharmony_ci 22677db96d56Sopenharmony_ci/* ************************************************************************ */ 22687db96d56Sopenharmony_ci 22697db96d56Sopenharmony_ci#include "clinic/selectmodule.c.h" 22707db96d56Sopenharmony_ci 22717db96d56Sopenharmony_ci#if defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL) 22727db96d56Sopenharmony_ci 22737db96d56Sopenharmony_cistatic PyMethodDef poll_methods[] = { 22747db96d56Sopenharmony_ci SELECT_POLL_REGISTER_METHODDEF 22757db96d56Sopenharmony_ci SELECT_POLL_MODIFY_METHODDEF 22767db96d56Sopenharmony_ci SELECT_POLL_UNREGISTER_METHODDEF 22777db96d56Sopenharmony_ci SELECT_POLL_POLL_METHODDEF 22787db96d56Sopenharmony_ci {NULL, NULL} /* sentinel */ 22797db96d56Sopenharmony_ci}; 22807db96d56Sopenharmony_ci 22817db96d56Sopenharmony_ci 22827db96d56Sopenharmony_cistatic PyType_Slot poll_Type_slots[] = { 22837db96d56Sopenharmony_ci {Py_tp_dealloc, poll_dealloc}, 22847db96d56Sopenharmony_ci {Py_tp_methods, poll_methods}, 22857db96d56Sopenharmony_ci {0, 0}, 22867db96d56Sopenharmony_ci}; 22877db96d56Sopenharmony_ci 22887db96d56Sopenharmony_cistatic PyType_Spec poll_Type_spec = { 22897db96d56Sopenharmony_ci .name = "select.poll", 22907db96d56Sopenharmony_ci .basicsize = sizeof(pollObject), 22917db96d56Sopenharmony_ci .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION, 22927db96d56Sopenharmony_ci .slots = poll_Type_slots, 22937db96d56Sopenharmony_ci}; 22947db96d56Sopenharmony_ci 22957db96d56Sopenharmony_ci#ifdef HAVE_SYS_DEVPOLL_H 22967db96d56Sopenharmony_ci 22977db96d56Sopenharmony_cistatic PyMethodDef devpoll_methods[] = { 22987db96d56Sopenharmony_ci SELECT_DEVPOLL_REGISTER_METHODDEF 22997db96d56Sopenharmony_ci SELECT_DEVPOLL_MODIFY_METHODDEF 23007db96d56Sopenharmony_ci SELECT_DEVPOLL_UNREGISTER_METHODDEF 23017db96d56Sopenharmony_ci SELECT_DEVPOLL_POLL_METHODDEF 23027db96d56Sopenharmony_ci SELECT_DEVPOLL_CLOSE_METHODDEF 23037db96d56Sopenharmony_ci SELECT_DEVPOLL_FILENO_METHODDEF 23047db96d56Sopenharmony_ci {NULL, NULL} /* sentinel */ 23057db96d56Sopenharmony_ci}; 23067db96d56Sopenharmony_ci 23077db96d56Sopenharmony_ci#endif /* HAVE_SYS_DEVPOLL_H */ 23087db96d56Sopenharmony_ci 23097db96d56Sopenharmony_ci#endif /* HAVE_POLL */ 23107db96d56Sopenharmony_ci 23117db96d56Sopenharmony_ci#ifdef HAVE_EPOLL 23127db96d56Sopenharmony_ci 23137db96d56Sopenharmony_cistatic PyMethodDef pyepoll_methods[] = { 23147db96d56Sopenharmony_ci SELECT_EPOLL_FROMFD_METHODDEF 23157db96d56Sopenharmony_ci SELECT_EPOLL_CLOSE_METHODDEF 23167db96d56Sopenharmony_ci SELECT_EPOLL_FILENO_METHODDEF 23177db96d56Sopenharmony_ci SELECT_EPOLL_MODIFY_METHODDEF 23187db96d56Sopenharmony_ci SELECT_EPOLL_REGISTER_METHODDEF 23197db96d56Sopenharmony_ci SELECT_EPOLL_UNREGISTER_METHODDEF 23207db96d56Sopenharmony_ci SELECT_EPOLL_POLL_METHODDEF 23217db96d56Sopenharmony_ci SELECT_EPOLL___ENTER___METHODDEF 23227db96d56Sopenharmony_ci SELECT_EPOLL___EXIT___METHODDEF 23237db96d56Sopenharmony_ci {NULL, NULL}, 23247db96d56Sopenharmony_ci}; 23257db96d56Sopenharmony_ci 23267db96d56Sopenharmony_cistatic PyType_Slot pyEpoll_Type_slots[] = { 23277db96d56Sopenharmony_ci {Py_tp_dealloc, pyepoll_dealloc}, 23287db96d56Sopenharmony_ci {Py_tp_doc, (void*)pyepoll_doc}, 23297db96d56Sopenharmony_ci {Py_tp_getattro, PyObject_GenericGetAttr}, 23307db96d56Sopenharmony_ci {Py_tp_getset, pyepoll_getsetlist}, 23317db96d56Sopenharmony_ci {Py_tp_methods, pyepoll_methods}, 23327db96d56Sopenharmony_ci {Py_tp_new, select_epoll}, 23337db96d56Sopenharmony_ci {0, 0}, 23347db96d56Sopenharmony_ci}; 23357db96d56Sopenharmony_ci 23367db96d56Sopenharmony_cistatic PyType_Spec pyEpoll_Type_spec = { 23377db96d56Sopenharmony_ci "select.epoll", 23387db96d56Sopenharmony_ci sizeof(pyEpoll_Object), 23397db96d56Sopenharmony_ci 0, 23407db96d56Sopenharmony_ci Py_TPFLAGS_DEFAULT, 23417db96d56Sopenharmony_ci pyEpoll_Type_slots 23427db96d56Sopenharmony_ci}; 23437db96d56Sopenharmony_ci 23447db96d56Sopenharmony_ci#endif /* HAVE_EPOLL */ 23457db96d56Sopenharmony_ci 23467db96d56Sopenharmony_ci#ifdef HAVE_KQUEUE 23477db96d56Sopenharmony_ci 23487db96d56Sopenharmony_cistatic PyMethodDef kqueue_queue_methods[] = { 23497db96d56Sopenharmony_ci SELECT_KQUEUE_FROMFD_METHODDEF 23507db96d56Sopenharmony_ci SELECT_KQUEUE_CLOSE_METHODDEF 23517db96d56Sopenharmony_ci SELECT_KQUEUE_FILENO_METHODDEF 23527db96d56Sopenharmony_ci SELECT_KQUEUE_CONTROL_METHODDEF 23537db96d56Sopenharmony_ci {NULL, NULL}, 23547db96d56Sopenharmony_ci}; 23557db96d56Sopenharmony_ci 23567db96d56Sopenharmony_cistatic PyType_Slot kqueue_queue_Type_slots[] = { 23577db96d56Sopenharmony_ci {Py_tp_dealloc, kqueue_queue_dealloc}, 23587db96d56Sopenharmony_ci {Py_tp_doc, (void*)select_kqueue__doc__}, 23597db96d56Sopenharmony_ci {Py_tp_getset, kqueue_queue_getsetlist}, 23607db96d56Sopenharmony_ci {Py_tp_methods, kqueue_queue_methods}, 23617db96d56Sopenharmony_ci {Py_tp_new, select_kqueue}, 23627db96d56Sopenharmony_ci {0, 0}, 23637db96d56Sopenharmony_ci}; 23647db96d56Sopenharmony_ci 23657db96d56Sopenharmony_cistatic PyType_Spec kqueue_queue_Type_spec = { 23667db96d56Sopenharmony_ci "select.kqueue", 23677db96d56Sopenharmony_ci sizeof(kqueue_queue_Object), 23687db96d56Sopenharmony_ci 0, 23697db96d56Sopenharmony_ci Py_TPFLAGS_DEFAULT, 23707db96d56Sopenharmony_ci kqueue_queue_Type_slots 23717db96d56Sopenharmony_ci}; 23727db96d56Sopenharmony_ci 23737db96d56Sopenharmony_ci#endif /* HAVE_KQUEUE */ 23747db96d56Sopenharmony_ci 23757db96d56Sopenharmony_ci 23767db96d56Sopenharmony_ci 23777db96d56Sopenharmony_ci 23787db96d56Sopenharmony_ci 23797db96d56Sopenharmony_ci/* ************************************************************************ */ 23807db96d56Sopenharmony_ci 23817db96d56Sopenharmony_ci 23827db96d56Sopenharmony_cistatic PyMethodDef select_methods[] = { 23837db96d56Sopenharmony_ci SELECT_SELECT_METHODDEF 23847db96d56Sopenharmony_ci SELECT_POLL_METHODDEF 23857db96d56Sopenharmony_ci SELECT_DEVPOLL_METHODDEF 23867db96d56Sopenharmony_ci {0, 0}, /* sentinel */ 23877db96d56Sopenharmony_ci}; 23887db96d56Sopenharmony_ci 23897db96d56Sopenharmony_ciPyDoc_STRVAR(module_doc, 23907db96d56Sopenharmony_ci"This module supports asynchronous I/O on multiple file descriptors.\n\ 23917db96d56Sopenharmony_ci\n\ 23927db96d56Sopenharmony_ci*** IMPORTANT NOTICE ***\n\ 23937db96d56Sopenharmony_ciOn Windows, only sockets are supported; on Unix, all file descriptors."); 23947db96d56Sopenharmony_ci 23957db96d56Sopenharmony_ci 23967db96d56Sopenharmony_ci 23977db96d56Sopenharmony_cistatic int 23987db96d56Sopenharmony_ci_select_traverse(PyObject *module, visitproc visit, void *arg) 23997db96d56Sopenharmony_ci{ 24007db96d56Sopenharmony_ci _selectstate *state = get_select_state(module); 24017db96d56Sopenharmony_ci 24027db96d56Sopenharmony_ci Py_VISIT(state->close); 24037db96d56Sopenharmony_ci Py_VISIT(state->poll_Type); 24047db96d56Sopenharmony_ci Py_VISIT(state->devpoll_Type); 24057db96d56Sopenharmony_ci Py_VISIT(state->pyEpoll_Type); 24067db96d56Sopenharmony_ci Py_VISIT(state->kqueue_event_Type); 24077db96d56Sopenharmony_ci Py_VISIT(state->kqueue_queue_Type); 24087db96d56Sopenharmony_ci return 0; 24097db96d56Sopenharmony_ci} 24107db96d56Sopenharmony_ci 24117db96d56Sopenharmony_cistatic int 24127db96d56Sopenharmony_ci_select_clear(PyObject *module) 24137db96d56Sopenharmony_ci{ 24147db96d56Sopenharmony_ci _selectstate *state = get_select_state(module); 24157db96d56Sopenharmony_ci 24167db96d56Sopenharmony_ci Py_CLEAR(state->close); 24177db96d56Sopenharmony_ci Py_CLEAR(state->poll_Type); 24187db96d56Sopenharmony_ci Py_CLEAR(state->devpoll_Type); 24197db96d56Sopenharmony_ci Py_CLEAR(state->pyEpoll_Type); 24207db96d56Sopenharmony_ci Py_CLEAR(state->kqueue_event_Type); 24217db96d56Sopenharmony_ci Py_CLEAR(state->kqueue_queue_Type); 24227db96d56Sopenharmony_ci return 0; 24237db96d56Sopenharmony_ci} 24247db96d56Sopenharmony_ci 24257db96d56Sopenharmony_cistatic void 24267db96d56Sopenharmony_ci_select_free(void *module) 24277db96d56Sopenharmony_ci{ 24287db96d56Sopenharmony_ci _select_clear((PyObject *)module); 24297db96d56Sopenharmony_ci} 24307db96d56Sopenharmony_ci 24317db96d56Sopenharmony_ciint 24327db96d56Sopenharmony_ci_select_exec(PyObject *m) 24337db96d56Sopenharmony_ci{ 24347db96d56Sopenharmony_ci _selectstate *state = get_select_state(m); 24357db96d56Sopenharmony_ci 24367db96d56Sopenharmony_ci state->close = PyUnicode_InternFromString("close"); 24377db96d56Sopenharmony_ci if (state->close == NULL) { 24387db96d56Sopenharmony_ci return -1; 24397db96d56Sopenharmony_ci } 24407db96d56Sopenharmony_ci if (PyModule_AddObjectRef(m, "error", PyExc_OSError) < 0) { 24417db96d56Sopenharmony_ci return -1; 24427db96d56Sopenharmony_ci } 24437db96d56Sopenharmony_ci 24447db96d56Sopenharmony_ci#ifdef PIPE_BUF 24457db96d56Sopenharmony_ci#ifdef HAVE_BROKEN_PIPE_BUF 24467db96d56Sopenharmony_ci#undef PIPE_BUF 24477db96d56Sopenharmony_ci#define PIPE_BUF 512 24487db96d56Sopenharmony_ci#endif 24497db96d56Sopenharmony_ci PyModule_AddIntMacro(m, PIPE_BUF); 24507db96d56Sopenharmony_ci#endif 24517db96d56Sopenharmony_ci 24527db96d56Sopenharmony_ci#if defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL) 24537db96d56Sopenharmony_ci#ifdef __APPLE__ 24547db96d56Sopenharmony_ci if (select_have_broken_poll()) { 24557db96d56Sopenharmony_ci if (PyObject_DelAttrString(m, "poll") == -1) { 24567db96d56Sopenharmony_ci PyErr_Clear(); 24577db96d56Sopenharmony_ci } 24587db96d56Sopenharmony_ci } else { 24597db96d56Sopenharmony_ci#else 24607db96d56Sopenharmony_ci { 24617db96d56Sopenharmony_ci#endif 24627db96d56Sopenharmony_ci state->poll_Type = (PyTypeObject *)PyType_FromModuleAndSpec( 24637db96d56Sopenharmony_ci m, &poll_Type_spec, NULL); 24647db96d56Sopenharmony_ci if (state->poll_Type == NULL) { 24657db96d56Sopenharmony_ci return -1; 24667db96d56Sopenharmony_ci } 24677db96d56Sopenharmony_ci 24687db96d56Sopenharmony_ci PyModule_AddIntMacro(m, POLLIN); 24697db96d56Sopenharmony_ci PyModule_AddIntMacro(m, POLLPRI); 24707db96d56Sopenharmony_ci PyModule_AddIntMacro(m, POLLOUT); 24717db96d56Sopenharmony_ci PyModule_AddIntMacro(m, POLLERR); 24727db96d56Sopenharmony_ci PyModule_AddIntMacro(m, POLLHUP); 24737db96d56Sopenharmony_ci PyModule_AddIntMacro(m, POLLNVAL); 24747db96d56Sopenharmony_ci 24757db96d56Sopenharmony_ci#ifdef POLLRDNORM 24767db96d56Sopenharmony_ci PyModule_AddIntMacro(m, POLLRDNORM); 24777db96d56Sopenharmony_ci#endif 24787db96d56Sopenharmony_ci#ifdef POLLRDBAND 24797db96d56Sopenharmony_ci PyModule_AddIntMacro(m, POLLRDBAND); 24807db96d56Sopenharmony_ci#endif 24817db96d56Sopenharmony_ci#ifdef POLLWRNORM 24827db96d56Sopenharmony_ci PyModule_AddIntMacro(m, POLLWRNORM); 24837db96d56Sopenharmony_ci#endif 24847db96d56Sopenharmony_ci#ifdef POLLWRBAND 24857db96d56Sopenharmony_ci PyModule_AddIntMacro(m, POLLWRBAND); 24867db96d56Sopenharmony_ci#endif 24877db96d56Sopenharmony_ci#ifdef POLLMSG 24887db96d56Sopenharmony_ci PyModule_AddIntMacro(m, POLLMSG); 24897db96d56Sopenharmony_ci#endif 24907db96d56Sopenharmony_ci#ifdef POLLRDHUP 24917db96d56Sopenharmony_ci /* Kernel 2.6.17+ */ 24927db96d56Sopenharmony_ci PyModule_AddIntMacro(m, POLLRDHUP); 24937db96d56Sopenharmony_ci#endif 24947db96d56Sopenharmony_ci } 24957db96d56Sopenharmony_ci#endif /* HAVE_POLL */ 24967db96d56Sopenharmony_ci 24977db96d56Sopenharmony_ci#ifdef HAVE_SYS_DEVPOLL_H 24987db96d56Sopenharmony_ci state->devpoll_Type = (PyTypeObject *)PyType_FromModuleAndSpec( 24997db96d56Sopenharmony_ci m, &devpoll_Type_spec, NULL); 25007db96d56Sopenharmony_ci if (state->devpoll_Type == NULL) { 25017db96d56Sopenharmony_ci return -1; 25027db96d56Sopenharmony_ci } 25037db96d56Sopenharmony_ci#endif 25047db96d56Sopenharmony_ci 25057db96d56Sopenharmony_ci#ifdef HAVE_EPOLL 25067db96d56Sopenharmony_ci state->pyEpoll_Type = (PyTypeObject *)PyType_FromModuleAndSpec( 25077db96d56Sopenharmony_ci m, &pyEpoll_Type_spec, NULL); 25087db96d56Sopenharmony_ci if (state->pyEpoll_Type == NULL) { 25097db96d56Sopenharmony_ci return -1; 25107db96d56Sopenharmony_ci } 25117db96d56Sopenharmony_ci if (PyModule_AddType(m, state->pyEpoll_Type) < 0) { 25127db96d56Sopenharmony_ci return -1; 25137db96d56Sopenharmony_ci } 25147db96d56Sopenharmony_ci 25157db96d56Sopenharmony_ci PyModule_AddIntMacro(m, EPOLLIN); 25167db96d56Sopenharmony_ci PyModule_AddIntMacro(m, EPOLLOUT); 25177db96d56Sopenharmony_ci PyModule_AddIntMacro(m, EPOLLPRI); 25187db96d56Sopenharmony_ci PyModule_AddIntMacro(m, EPOLLERR); 25197db96d56Sopenharmony_ci PyModule_AddIntMacro(m, EPOLLHUP); 25207db96d56Sopenharmony_ci#ifdef EPOLLRDHUP 25217db96d56Sopenharmony_ci /* Kernel 2.6.17 */ 25227db96d56Sopenharmony_ci PyModule_AddIntMacro(m, EPOLLRDHUP); 25237db96d56Sopenharmony_ci#endif 25247db96d56Sopenharmony_ci PyModule_AddIntMacro(m, EPOLLET); 25257db96d56Sopenharmony_ci#ifdef EPOLLONESHOT 25267db96d56Sopenharmony_ci /* Kernel 2.6.2+ */ 25277db96d56Sopenharmony_ci PyModule_AddIntMacro(m, EPOLLONESHOT); 25287db96d56Sopenharmony_ci#endif 25297db96d56Sopenharmony_ci#ifdef EPOLLEXCLUSIVE 25307db96d56Sopenharmony_ci PyModule_AddIntMacro(m, EPOLLEXCLUSIVE); 25317db96d56Sopenharmony_ci#endif 25327db96d56Sopenharmony_ci 25337db96d56Sopenharmony_ci#ifdef EPOLLRDNORM 25347db96d56Sopenharmony_ci PyModule_AddIntMacro(m, EPOLLRDNORM); 25357db96d56Sopenharmony_ci#endif 25367db96d56Sopenharmony_ci#ifdef EPOLLRDBAND 25377db96d56Sopenharmony_ci PyModule_AddIntMacro(m, EPOLLRDBAND); 25387db96d56Sopenharmony_ci#endif 25397db96d56Sopenharmony_ci#ifdef EPOLLWRNORM 25407db96d56Sopenharmony_ci PyModule_AddIntMacro(m, EPOLLWRNORM); 25417db96d56Sopenharmony_ci#endif 25427db96d56Sopenharmony_ci#ifdef EPOLLWRBAND 25437db96d56Sopenharmony_ci PyModule_AddIntMacro(m, EPOLLWRBAND); 25447db96d56Sopenharmony_ci#endif 25457db96d56Sopenharmony_ci#ifdef EPOLLMSG 25467db96d56Sopenharmony_ci PyModule_AddIntMacro(m, EPOLLMSG); 25477db96d56Sopenharmony_ci#endif 25487db96d56Sopenharmony_ci 25497db96d56Sopenharmony_ci#ifdef EPOLL_CLOEXEC 25507db96d56Sopenharmony_ci PyModule_AddIntMacro(m, EPOLL_CLOEXEC); 25517db96d56Sopenharmony_ci#endif 25527db96d56Sopenharmony_ci#endif /* HAVE_EPOLL */ 25537db96d56Sopenharmony_ci 25547db96d56Sopenharmony_ci#ifdef HAVE_KQUEUE 25557db96d56Sopenharmony_ci state->kqueue_event_Type = (PyTypeObject *)PyType_FromModuleAndSpec( 25567db96d56Sopenharmony_ci m, &kqueue_event_Type_spec, NULL); 25577db96d56Sopenharmony_ci if (state->kqueue_event_Type == NULL) { 25587db96d56Sopenharmony_ci return -1; 25597db96d56Sopenharmony_ci } 25607db96d56Sopenharmony_ci if (PyModule_AddType(m, state->kqueue_event_Type) < 0) { 25617db96d56Sopenharmony_ci return -1; 25627db96d56Sopenharmony_ci } 25637db96d56Sopenharmony_ci 25647db96d56Sopenharmony_ci state->kqueue_queue_Type = (PyTypeObject *)PyType_FromModuleAndSpec( 25657db96d56Sopenharmony_ci m, &kqueue_queue_Type_spec, NULL); 25667db96d56Sopenharmony_ci if (state->kqueue_queue_Type == NULL) { 25677db96d56Sopenharmony_ci return -1; 25687db96d56Sopenharmony_ci } 25697db96d56Sopenharmony_ci if (PyModule_AddType(m, state->kqueue_queue_Type) < 0) { 25707db96d56Sopenharmony_ci return -1; 25717db96d56Sopenharmony_ci } 25727db96d56Sopenharmony_ci 25737db96d56Sopenharmony_ci /* event filters */ 25747db96d56Sopenharmony_ci PyModule_AddIntConstant(m, "KQ_FILTER_READ", EVFILT_READ); 25757db96d56Sopenharmony_ci PyModule_AddIntConstant(m, "KQ_FILTER_WRITE", EVFILT_WRITE); 25767db96d56Sopenharmony_ci#ifdef EVFILT_AIO 25777db96d56Sopenharmony_ci PyModule_AddIntConstant(m, "KQ_FILTER_AIO", EVFILT_AIO); 25787db96d56Sopenharmony_ci#endif 25797db96d56Sopenharmony_ci#ifdef EVFILT_VNODE 25807db96d56Sopenharmony_ci PyModule_AddIntConstant(m, "KQ_FILTER_VNODE", EVFILT_VNODE); 25817db96d56Sopenharmony_ci#endif 25827db96d56Sopenharmony_ci#ifdef EVFILT_PROC 25837db96d56Sopenharmony_ci PyModule_AddIntConstant(m, "KQ_FILTER_PROC", EVFILT_PROC); 25847db96d56Sopenharmony_ci#endif 25857db96d56Sopenharmony_ci#ifdef EVFILT_NETDEV 25867db96d56Sopenharmony_ci PyModule_AddIntConstant(m, "KQ_FILTER_NETDEV", EVFILT_NETDEV); 25877db96d56Sopenharmony_ci#endif 25887db96d56Sopenharmony_ci#ifdef EVFILT_SIGNAL 25897db96d56Sopenharmony_ci PyModule_AddIntConstant(m, "KQ_FILTER_SIGNAL", EVFILT_SIGNAL); 25907db96d56Sopenharmony_ci#endif 25917db96d56Sopenharmony_ci PyModule_AddIntConstant(m, "KQ_FILTER_TIMER", EVFILT_TIMER); 25927db96d56Sopenharmony_ci 25937db96d56Sopenharmony_ci /* event flags */ 25947db96d56Sopenharmony_ci PyModule_AddIntConstant(m, "KQ_EV_ADD", EV_ADD); 25957db96d56Sopenharmony_ci PyModule_AddIntConstant(m, "KQ_EV_DELETE", EV_DELETE); 25967db96d56Sopenharmony_ci PyModule_AddIntConstant(m, "KQ_EV_ENABLE", EV_ENABLE); 25977db96d56Sopenharmony_ci PyModule_AddIntConstant(m, "KQ_EV_DISABLE", EV_DISABLE); 25987db96d56Sopenharmony_ci PyModule_AddIntConstant(m, "KQ_EV_ONESHOT", EV_ONESHOT); 25997db96d56Sopenharmony_ci PyModule_AddIntConstant(m, "KQ_EV_CLEAR", EV_CLEAR); 26007db96d56Sopenharmony_ci 26017db96d56Sopenharmony_ci#ifdef EV_SYSFLAGS 26027db96d56Sopenharmony_ci PyModule_AddIntConstant(m, "KQ_EV_SYSFLAGS", EV_SYSFLAGS); 26037db96d56Sopenharmony_ci#endif 26047db96d56Sopenharmony_ci#ifdef EV_FLAG1 26057db96d56Sopenharmony_ci PyModule_AddIntConstant(m, "KQ_EV_FLAG1", EV_FLAG1); 26067db96d56Sopenharmony_ci#endif 26077db96d56Sopenharmony_ci 26087db96d56Sopenharmony_ci PyModule_AddIntConstant(m, "KQ_EV_EOF", EV_EOF); 26097db96d56Sopenharmony_ci PyModule_AddIntConstant(m, "KQ_EV_ERROR", EV_ERROR); 26107db96d56Sopenharmony_ci 26117db96d56Sopenharmony_ci /* READ WRITE filter flag */ 26127db96d56Sopenharmony_ci#ifdef NOTE_LOWAT 26137db96d56Sopenharmony_ci PyModule_AddIntConstant(m, "KQ_NOTE_LOWAT", NOTE_LOWAT); 26147db96d56Sopenharmony_ci#endif 26157db96d56Sopenharmony_ci 26167db96d56Sopenharmony_ci /* VNODE filter flags */ 26177db96d56Sopenharmony_ci#ifdef EVFILT_VNODE 26187db96d56Sopenharmony_ci PyModule_AddIntConstant(m, "KQ_NOTE_DELETE", NOTE_DELETE); 26197db96d56Sopenharmony_ci PyModule_AddIntConstant(m, "KQ_NOTE_WRITE", NOTE_WRITE); 26207db96d56Sopenharmony_ci PyModule_AddIntConstant(m, "KQ_NOTE_EXTEND", NOTE_EXTEND); 26217db96d56Sopenharmony_ci PyModule_AddIntConstant(m, "KQ_NOTE_ATTRIB", NOTE_ATTRIB); 26227db96d56Sopenharmony_ci PyModule_AddIntConstant(m, "KQ_NOTE_LINK", NOTE_LINK); 26237db96d56Sopenharmony_ci PyModule_AddIntConstant(m, "KQ_NOTE_RENAME", NOTE_RENAME); 26247db96d56Sopenharmony_ci PyModule_AddIntConstant(m, "KQ_NOTE_REVOKE", NOTE_REVOKE); 26257db96d56Sopenharmony_ci#endif 26267db96d56Sopenharmony_ci 26277db96d56Sopenharmony_ci /* PROC filter flags */ 26287db96d56Sopenharmony_ci#ifdef EVFILT_PROC 26297db96d56Sopenharmony_ci PyModule_AddIntConstant(m, "KQ_NOTE_EXIT", NOTE_EXIT); 26307db96d56Sopenharmony_ci PyModule_AddIntConstant(m, "KQ_NOTE_FORK", NOTE_FORK); 26317db96d56Sopenharmony_ci PyModule_AddIntConstant(m, "KQ_NOTE_EXEC", NOTE_EXEC); 26327db96d56Sopenharmony_ci PyModule_AddIntConstant(m, "KQ_NOTE_PCTRLMASK", NOTE_PCTRLMASK); 26337db96d56Sopenharmony_ci PyModule_AddIntConstant(m, "KQ_NOTE_PDATAMASK", NOTE_PDATAMASK); 26347db96d56Sopenharmony_ci 26357db96d56Sopenharmony_ci PyModule_AddIntConstant(m, "KQ_NOTE_TRACK", NOTE_TRACK); 26367db96d56Sopenharmony_ci PyModule_AddIntConstant(m, "KQ_NOTE_CHILD", NOTE_CHILD); 26377db96d56Sopenharmony_ci PyModule_AddIntConstant(m, "KQ_NOTE_TRACKERR", NOTE_TRACKERR); 26387db96d56Sopenharmony_ci#endif 26397db96d56Sopenharmony_ci 26407db96d56Sopenharmony_ci /* NETDEV filter flags */ 26417db96d56Sopenharmony_ci#ifdef EVFILT_NETDEV 26427db96d56Sopenharmony_ci PyModule_AddIntConstant(m, "KQ_NOTE_LINKUP", NOTE_LINKUP); 26437db96d56Sopenharmony_ci PyModule_AddIntConstant(m, "KQ_NOTE_LINKDOWN", NOTE_LINKDOWN); 26447db96d56Sopenharmony_ci PyModule_AddIntConstant(m, "KQ_NOTE_LINKINV", NOTE_LINKINV); 26457db96d56Sopenharmony_ci#endif 26467db96d56Sopenharmony_ci 26477db96d56Sopenharmony_ci#endif /* HAVE_KQUEUE */ 26487db96d56Sopenharmony_ci return 0; 26497db96d56Sopenharmony_ci} 26507db96d56Sopenharmony_ci 26517db96d56Sopenharmony_cistatic PyModuleDef_Slot _select_slots[] = { 26527db96d56Sopenharmony_ci {Py_mod_exec, _select_exec}, 26537db96d56Sopenharmony_ci {0, NULL} 26547db96d56Sopenharmony_ci}; 26557db96d56Sopenharmony_ci 26567db96d56Sopenharmony_cistatic struct PyModuleDef selectmodule = { 26577db96d56Sopenharmony_ci PyModuleDef_HEAD_INIT, 26587db96d56Sopenharmony_ci .m_name = "select", 26597db96d56Sopenharmony_ci .m_doc = module_doc, 26607db96d56Sopenharmony_ci .m_size = sizeof(_selectstate), 26617db96d56Sopenharmony_ci .m_methods = select_methods, 26627db96d56Sopenharmony_ci .m_slots = _select_slots, 26637db96d56Sopenharmony_ci .m_traverse = _select_traverse, 26647db96d56Sopenharmony_ci .m_clear = _select_clear, 26657db96d56Sopenharmony_ci .m_free = _select_free, 26667db96d56Sopenharmony_ci}; 26677db96d56Sopenharmony_ci 26687db96d56Sopenharmony_ciPyMODINIT_FUNC 26697db96d56Sopenharmony_ciPyInit_select(void) 26707db96d56Sopenharmony_ci{ 26717db96d56Sopenharmony_ci return PyModuleDef_Init(&selectmodule); 26727db96d56Sopenharmony_ci} 2673