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