LCOV - code coverage report
Current view: top level - Modules - selectmodule.c (source / functions) Hit Total Coverage
Test: CPython 3.12 LCOV report [commit acb105a7c1f] Lines: 423 504 83.9 %
Date: 2022-07-20 13:12:14 Functions: 34 34 100.0 %
Branches: 198 281 70.5 %

           Branch data     Line data    Source code
       1                 :            : /* select - Module containing unix select(2) call.
       2                 :            :    Under Unix, the file descriptors are small integers.
       3                 :            :    Under Win32, select only exists for sockets, and sockets may
       4                 :            :    have any value except INVALID_SOCKET.
       5                 :            : */
       6                 :            : 
       7                 :            : #ifndef Py_BUILD_CORE_BUILTIN
       8                 :            : #  define Py_BUILD_CORE_MODULE 1
       9                 :            : #endif
      10                 :            : 
      11                 :            : #if defined(HAVE_POLL_H) && !defined(_GNU_SOURCE)
      12                 :            : #  define _GNU_SOURCE
      13                 :            : #endif
      14                 :            : 
      15                 :            : #include "Python.h"
      16                 :            : #include "pycore_fileutils.h"     // _Py_set_inheritable()
      17                 :            : #include "structmember.h"         // PyMemberDef
      18                 :            : 
      19                 :            : #ifdef HAVE_SYS_DEVPOLL_H
      20                 :            : #include <sys/resource.h>
      21                 :            : #include <sys/devpoll.h>
      22                 :            : #include <sys/types.h>
      23                 :            : #include <sys/stat.h>
      24                 :            : #include <fcntl.h>
      25                 :            : #endif
      26                 :            : 
      27                 :            : #ifdef __APPLE__
      28                 :            :     /* Perform runtime testing for a broken poll on OSX to make it easier
      29                 :            :      * to use the same binary on multiple releases of the OS.
      30                 :            :      */
      31                 :            : #undef HAVE_BROKEN_POLL
      32                 :            : #endif
      33                 :            : 
      34                 :            : /* Windows #defines FD_SETSIZE to 64 if FD_SETSIZE isn't already defined.
      35                 :            :    64 is too small (too many people have bumped into that limit).
      36                 :            :    Here we boost it.
      37                 :            :    Users who want even more than the boosted limit should #define
      38                 :            :    FD_SETSIZE higher before this; e.g., via compiler /D switch.
      39                 :            : */
      40                 :            : #if defined(MS_WINDOWS) && !defined(FD_SETSIZE)
      41                 :            : #define FD_SETSIZE 512
      42                 :            : #endif
      43                 :            : 
      44                 :            : #if defined(HAVE_POLL_H)
      45                 :            : #include <poll.h>
      46                 :            : #elif defined(HAVE_SYS_POLL_H)
      47                 :            : #include <sys/poll.h>
      48                 :            : #endif
      49                 :            : 
      50                 :            : #ifdef __sgi
      51                 :            : /* This is missing from unistd.h */
      52                 :            : extern void bzero(void *, int);
      53                 :            : #endif
      54                 :            : 
      55                 :            : #ifdef HAVE_SYS_TYPES_H
      56                 :            : #include <sys/types.h>
      57                 :            : #endif
      58                 :            : 
      59                 :            : #ifdef MS_WINDOWS
      60                 :            : #  define WIN32_LEAN_AND_MEAN
      61                 :            : #  include <winsock.h>
      62                 :            : #else
      63                 :            : #  define SOCKET int
      64                 :            : #endif
      65                 :            : 
      66                 :            : typedef struct {
      67                 :            :     PyObject *close;
      68                 :            :     PyTypeObject *poll_Type;
      69                 :            :     PyTypeObject *devpoll_Type;
      70                 :            :     PyTypeObject *pyEpoll_Type;
      71                 :            :     PyTypeObject *kqueue_event_Type;
      72                 :            :     PyTypeObject *kqueue_queue_Type;
      73                 :            : } _selectstate;
      74                 :            : 
      75                 :            : static struct PyModuleDef selectmodule;
      76                 :            : 
      77                 :            : static inline _selectstate*
      78                 :      66201 : get_select_state(PyObject *module)
      79                 :            : {
      80                 :      66201 :     void *state = PyModule_GetState(module);
      81                 :            :     assert(state != NULL);
      82                 :      66201 :     return (_selectstate *)state;
      83                 :            : }
      84                 :            : 
      85                 :            : #define _selectstate_by_type(type) get_select_state(PyType_GetModule(type))
      86                 :            : 
      87                 :            : /*[clinic input]
      88                 :            : module select
      89                 :            : class select.poll "pollObject *" "_selectstate_by_type(type)->poll_Type"
      90                 :            : class select.devpoll "devpollObject *" "_selectstate_by_type(type)->devpoll_Type"
      91                 :            : class select.epoll "pyEpoll_Object *" "_selectstate_by_type(type)->pyEpoll_Type"
      92                 :            : class select.kqueue "kqueue_queue_Object *" "_selectstate_by_type(type)->kqueue_queue_Type"
      93                 :            : [clinic start generated code]*/
      94                 :            : /*[clinic end generated code: output=da39a3ee5e6b4b0d input=8072de35824aa327]*/
      95                 :            : 
      96                 :            : /* list of Python objects and their file descriptor */
      97                 :            : typedef struct {
      98                 :            :     PyObject *obj;                           /* owned reference */
      99                 :            :     SOCKET fd;
     100                 :            :     int sentinel;                            /* -1 == sentinel */
     101                 :            : } pylist;
     102                 :            : 
     103                 :            : static void
     104                 :      75990 : reap_obj(pylist fd2obj[FD_SETSIZE + 1])
     105                 :            : {
     106                 :            :     unsigned int i;
     107   [ +  -  +  + ]:     128691 :     for (i = 0; i < (unsigned int)FD_SETSIZE + 1 && fd2obj[i].sentinel >= 0; i++) {
     108         [ +  + ]:      52701 :         Py_CLEAR(fd2obj[i].obj);
     109                 :            :     }
     110                 :      75990 :     fd2obj[0].sentinel = -1;
     111                 :      75990 : }
     112                 :            : 
     113                 :            : 
     114                 :            : /* returns -1 and sets the Python exception if an error occurred, otherwise
     115                 :            :    returns a number >= 0
     116                 :            : */
     117                 :            : static int
     118                 :      75984 : seq2set(PyObject *seq, fd_set *set, pylist fd2obj[FD_SETSIZE + 1])
     119                 :            : {
     120                 :      75984 :     int max = -1;
     121                 :      75984 :     unsigned int index = 0;
     122                 :            :     Py_ssize_t i;
     123                 :      75984 :     PyObject* fast_seq = NULL;
     124                 :      75984 :     PyObject* o = NULL;
     125                 :            : 
     126                 :      75984 :     fd2obj[0].obj = (PyObject*)0;            /* set list to zero size */
     127         [ +  + ]:    1291728 :     FD_ZERO(set);
     128                 :            : 
     129                 :      75984 :     fast_seq = PySequence_Fast(seq, "arguments 1-3 must be sequences");
     130         [ +  + ]:      75984 :     if (!fast_seq)
     131                 :          1 :         return -1;
     132                 :            : 
     133   [ +  +  +  + ]:     128684 :     for (i = 0; i < PySequence_Fast_GET_SIZE(fast_seq); i++)  {
     134                 :            :         SOCKET v;
     135                 :            : 
     136                 :            :         /* any intervening fileno() calls could decr this refcnt */
     137   [ +  -  -  + ]:      52703 :         if (!(o = PySequence_Fast_GET_ITEM(fast_seq, i)))
     138                 :          0 :             goto finally;
     139                 :            : 
     140                 :      52703 :         Py_INCREF(o);
     141                 :      52703 :         v = PyObject_AsFileDescriptor( o );
     142         [ +  + ]:      52703 :         if (v == -1) goto finally;
     143                 :            : 
     144                 :            : #if defined(_MSC_VER)
     145                 :            :         max = 0;                             /* not used for Win32 */
     146                 :            : #else  /* !_MSC_VER */
     147         [ -  + ]:      52701 :         if (!_PyIsSelectable_fd(v)) {
     148                 :          0 :             PyErr_SetString(PyExc_ValueError,
     149                 :            :                         "filedescriptor out of range in select()");
     150                 :          0 :             goto finally;
     151                 :            :         }
     152         [ +  + ]:      52701 :         if (v > max)
     153                 :      49711 :             max = v;
     154                 :            : #endif /* _MSC_VER */
     155                 :      52701 :         FD_SET(v, set);
     156                 :            : 
     157                 :            :         /* add object and its file descriptor to the list */
     158         [ -  + ]:      52701 :         if (index >= (unsigned int)FD_SETSIZE) {
     159                 :          0 :             PyErr_SetString(PyExc_ValueError,
     160                 :            :                           "too many file descriptors in select()");
     161                 :          0 :             goto finally;
     162                 :            :         }
     163                 :      52701 :         fd2obj[index].obj = o;
     164                 :      52701 :         fd2obj[index].fd = v;
     165                 :      52701 :         fd2obj[index].sentinel = 0;
     166                 :      52701 :         fd2obj[++index].sentinel = -1;
     167                 :            :     }
     168                 :      75981 :     Py_DECREF(fast_seq);
     169                 :      75981 :     return max+1;
     170                 :            : 
     171                 :          2 :   finally:
     172                 :          2 :     Py_XDECREF(o);
     173                 :          2 :     Py_DECREF(fast_seq);
     174                 :          2 :     return -1;
     175                 :            : }
     176                 :            : 
     177                 :            : /* returns NULL and sets the Python exception if an error occurred */
     178                 :            : static PyObject *
     179                 :      75969 : set2list(fd_set *set, pylist fd2obj[FD_SETSIZE + 1])
     180                 :            : {
     181                 :      75969 :     int i, j, count=0;
     182                 :            :     PyObject *list, *o;
     183                 :            :     SOCKET fd;
     184                 :            : 
     185         [ +  + ]:     128667 :     for (j = 0; fd2obj[j].sentinel >= 0; j++) {
     186         [ +  + ]:      52698 :         if (FD_ISSET(fd2obj[j].fd, set))
     187                 :      24992 :             count++;
     188                 :            :     }
     189                 :      75969 :     list = PyList_New(count);
     190         [ -  + ]:      75969 :     if (!list)
     191                 :          0 :         return NULL;
     192                 :            : 
     193                 :      75969 :     i = 0;
     194         [ +  + ]:     128667 :     for (j = 0; fd2obj[j].sentinel >= 0; j++) {
     195                 :      52698 :         fd = fd2obj[j].fd;
     196         [ +  + ]:      52698 :         if (FD_ISSET(fd, set)) {
     197                 :      24992 :             o = fd2obj[j].obj;
     198                 :      24992 :             fd2obj[j].obj = NULL;
     199                 :            :             /* transfer ownership */
     200         [ -  + ]:      24992 :             if (PyList_SetItem(list, i, o) < 0)
     201                 :          0 :                 goto finally;
     202                 :            : 
     203                 :      24992 :             i++;
     204                 :            :         }
     205                 :            :     }
     206                 :      75969 :     return list;
     207                 :          0 :   finally:
     208                 :          0 :     Py_DECREF(list);
     209                 :          0 :     return NULL;
     210                 :            : }
     211                 :            : 
     212                 :            : #undef SELECT_USES_HEAP
     213                 :            : #if FD_SETSIZE > 1024
     214                 :            : #define SELECT_USES_HEAP
     215                 :            : #endif /* FD_SETSIZE > 1024 */
     216                 :            : 
     217                 :            : /*[clinic input]
     218                 :            : select.select
     219                 :            : 
     220                 :            :     rlist: object
     221                 :            :     wlist: object
     222                 :            :     xlist: object
     223                 :            :     timeout as timeout_obj: object = None
     224                 :            :     /
     225                 :            : 
     226                 :            : Wait until one or more file descriptors are ready for some kind of I/O.
     227                 :            : 
     228                 :            : The first three arguments are iterables of file descriptors to be waited for:
     229                 :            : rlist -- wait until ready for reading
     230                 :            : wlist -- wait until ready for writing
     231                 :            : xlist -- wait for an "exceptional condition"
     232                 :            : If only one kind of condition is required, pass [] for the other lists.
     233                 :            : 
     234                 :            : A file descriptor is either a socket or file object, or a small integer
     235                 :            : gotten from a fileno() method call on one of those.
     236                 :            : 
     237                 :            : The optional 4th argument specifies a timeout in seconds; it may be
     238                 :            : a floating point number to specify fractions of seconds.  If it is absent
     239                 :            : or None, the call will never time out.
     240                 :            : 
     241                 :            : The return value is a tuple of three lists corresponding to the first three
     242                 :            : arguments; each contains the subset of the corresponding file descriptors
     243                 :            : that are ready.
     244                 :            : 
     245                 :            : *** IMPORTANT NOTICE ***
     246                 :            : On Windows, only sockets are supported; on Unix, all file
     247                 :            : descriptors can be used.
     248                 :            : [clinic start generated code]*/
     249                 :            : 
     250                 :            : static PyObject *
     251                 :      25332 : select_select_impl(PyObject *module, PyObject *rlist, PyObject *wlist,
     252                 :            :                    PyObject *xlist, PyObject *timeout_obj)
     253                 :            : /*[clinic end generated code: output=2b3cfa824f7ae4cf input=e467f5d68033de00]*/
     254                 :            : {
     255                 :            : #ifdef SELECT_USES_HEAP
     256                 :            :     pylist *rfd2obj, *wfd2obj, *efd2obj;
     257                 :            : #else  /* !SELECT_USES_HEAP */
     258                 :            :     /* XXX: All this should probably be implemented as follows:
     259                 :            :      * - find the highest descriptor we're interested in
     260                 :            :      * - add one
     261                 :            :      * - that's the size
     262                 :            :      * See: Stevens, APitUE, $12.5.1
     263                 :            :      */
     264                 :            :     pylist rfd2obj[FD_SETSIZE + 1];
     265                 :            :     pylist wfd2obj[FD_SETSIZE + 1];
     266                 :            :     pylist efd2obj[FD_SETSIZE + 1];
     267                 :            : #endif /* SELECT_USES_HEAP */
     268                 :      25332 :     PyObject *ret = NULL;
     269                 :            :     fd_set ifdset, ofdset, efdset;
     270                 :            :     struct timeval tv, *tvp;
     271                 :            :     int imax, omax, emax, max;
     272                 :            :     int n;
     273                 :      25332 :     _PyTime_t timeout, deadline = 0;
     274                 :            : 
     275         [ +  + ]:      25332 :     if (timeout_obj == Py_None)
     276                 :       2469 :         tvp = (struct timeval *)NULL;
     277                 :            :     else {
     278         [ +  + ]:      22863 :         if (_PyTime_FromSecondsObject(&timeout, timeout_obj,
     279                 :            :                                       _PyTime_ROUND_TIMEOUT) < 0) {
     280         [ +  - ]:          1 :             if (PyErr_ExceptionMatches(PyExc_TypeError)) {
     281                 :          1 :                 PyErr_SetString(PyExc_TypeError,
     282                 :            :                                 "timeout must be a float or None");
     283                 :            :             }
     284                 :          1 :             return NULL;
     285                 :            :         }
     286                 :            : 
     287         [ -  + ]:      22862 :         if (_PyTime_AsTimeval(timeout, &tv, _PyTime_ROUND_TIMEOUT) == -1)
     288                 :          0 :             return NULL;
     289         [ +  + ]:      22862 :         if (tv.tv_sec < 0) {
     290                 :          1 :             PyErr_SetString(PyExc_ValueError, "timeout must be non-negative");
     291                 :          1 :             return NULL;
     292                 :            :         }
     293                 :      22861 :         tvp = &tv;
     294                 :            :     }
     295                 :            : 
     296                 :            : #ifdef SELECT_USES_HEAP
     297                 :            :     /* Allocate memory for the lists */
     298                 :            :     rfd2obj = PyMem_NEW(pylist, FD_SETSIZE + 1);
     299                 :            :     wfd2obj = PyMem_NEW(pylist, FD_SETSIZE + 1);
     300                 :            :     efd2obj = PyMem_NEW(pylist, FD_SETSIZE + 1);
     301                 :            :     if (rfd2obj == NULL || wfd2obj == NULL || efd2obj == NULL) {
     302                 :            :         if (rfd2obj) PyMem_Free(rfd2obj);
     303                 :            :         if (wfd2obj) PyMem_Free(wfd2obj);
     304                 :            :         if (efd2obj) PyMem_Free(efd2obj);
     305                 :            :         return PyErr_NoMemory();
     306                 :            :     }
     307                 :            : #endif /* SELECT_USES_HEAP */
     308                 :            : 
     309                 :            :     /* Convert iterables to fd_sets, and get maximum fd number
     310                 :            :      * propagates the Python exception set in seq2set()
     311                 :            :      */
     312                 :      25330 :     rfd2obj[0].sentinel = -1;
     313                 :      25330 :     wfd2obj[0].sentinel = -1;
     314                 :      25330 :     efd2obj[0].sentinel = -1;
     315         [ +  + ]:      25330 :     if ((imax = seq2set(rlist, &ifdset, rfd2obj)) < 0)
     316                 :          3 :         goto finally;
     317         [ -  + ]:      25327 :     if ((omax = seq2set(wlist, &ofdset, wfd2obj)) < 0)
     318                 :          0 :         goto finally;
     319         [ -  + ]:      25327 :     if ((emax = seq2set(xlist, &efdset, efd2obj)) < 0)
     320                 :          0 :         goto finally;
     321                 :            : 
     322                 :      25327 :     max = imax;
     323         [ +  + ]:      25327 :     if (omax > max) max = omax;
     324         [ -  + ]:      25327 :     if (emax > max) max = emax;
     325                 :            : 
     326         [ +  + ]:      25327 :     if (tvp) {
     327                 :      22861 :         deadline = _PyDeadline_Init(timeout);
     328                 :            :     }
     329                 :            : 
     330                 :            :     do {
     331                 :      25340 :         Py_BEGIN_ALLOW_THREADS
     332                 :      25340 :         errno = 0;
     333   [ +  +  +  +  :      25340 :         n = select(
                   +  + ]
     334                 :            :             max,
     335                 :            :             imax ? &ifdset : NULL,
     336                 :            :             omax ? &ofdset : NULL,
     337                 :            :             emax ? &efdset : NULL,
     338                 :            :             tvp);
     339                 :      25340 :         Py_END_ALLOW_THREADS
     340                 :            : 
     341         [ +  + ]:      25340 :         if (errno != EINTR)
     342                 :      25324 :             break;
     343                 :            : 
     344                 :            :         /* select() was interrupted by a signal */
     345         [ +  + ]:         16 :         if (PyErr_CheckSignals())
     346                 :          3 :             goto finally;
     347                 :            : 
     348         [ +  + ]:         13 :         if (tvp) {
     349                 :          5 :             timeout = _PyDeadline_Get(deadline);
     350         [ -  + ]:          5 :             if (timeout < 0) {
     351                 :            :                 /* bpo-35310: lists were unmodified -- clear them explicitly */
     352         [ #  # ]:          0 :                 FD_ZERO(&ifdset);
     353         [ #  # ]:          0 :                 FD_ZERO(&ofdset);
     354         [ #  # ]:          0 :                 FD_ZERO(&efdset);
     355                 :          0 :                 n = 0;
     356                 :          0 :                 break;
     357                 :            :             }
     358                 :          5 :             _PyTime_AsTimeval_clamp(timeout, &tv, _PyTime_ROUND_CEILING);
     359                 :            :             /* retry select() with the recomputed timeout */
     360                 :            :         }
     361                 :            :     } while (1);
     362                 :            : 
     363                 :            : #ifdef MS_WINDOWS
     364                 :            :     if (n == SOCKET_ERROR) {
     365                 :            :         PyErr_SetExcFromWindowsErr(PyExc_OSError, WSAGetLastError());
     366                 :            :     }
     367                 :            : #else
     368         [ +  + ]:      25324 :     if (n < 0) {
     369                 :          1 :         PyErr_SetFromErrno(PyExc_OSError);
     370                 :            :     }
     371                 :            : #endif
     372                 :            :     else {
     373                 :            :         /* any of these three calls can raise an exception.  it's more
     374                 :            :            convenient to test for this after all three calls... but
     375                 :            :            is that acceptable?
     376                 :            :         */
     377                 :      25323 :         rlist = set2list(&ifdset, rfd2obj);
     378                 :      25323 :         wlist = set2list(&ofdset, wfd2obj);
     379                 :      25323 :         xlist = set2list(&efdset, efd2obj);
     380         [ -  + ]:      25323 :         if (PyErr_Occurred())
     381                 :          0 :             ret = NULL;
     382                 :            :         else
     383                 :      25323 :             ret = PyTuple_Pack(3, rlist, wlist, xlist);
     384                 :            : 
     385                 :      25323 :         Py_XDECREF(rlist);
     386                 :      25323 :         Py_XDECREF(wlist);
     387                 :      25323 :         Py_XDECREF(xlist);
     388                 :            :     }
     389                 :            : 
     390                 :      25330 :   finally:
     391                 :      25330 :     reap_obj(rfd2obj);
     392                 :      25330 :     reap_obj(wfd2obj);
     393                 :      25330 :     reap_obj(efd2obj);
     394                 :            : #ifdef SELECT_USES_HEAP
     395                 :            :     PyMem_Free(rfd2obj);
     396                 :            :     PyMem_Free(wfd2obj);
     397                 :            :     PyMem_Free(efd2obj);
     398                 :            : #endif /* SELECT_USES_HEAP */
     399                 :      25330 :     return ret;
     400                 :            : }
     401                 :            : 
     402                 :            : #if defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL)
     403                 :            : /*
     404                 :            :  * poll() support
     405                 :            :  */
     406                 :            : 
     407                 :            : typedef struct {
     408                 :            :     PyObject_HEAD
     409                 :            :     PyObject *dict;
     410                 :            :     int ufd_uptodate;
     411                 :            :     int ufd_len;
     412                 :            :     struct pollfd *ufds;
     413                 :            :     int poll_running;
     414                 :            : } pollObject;
     415                 :            : 
     416                 :            : /* Update the malloc'ed array of pollfds to match the dictionary
     417                 :            :    contained within a pollObject.  Return 1 on success, 0 on an error.
     418                 :            : */
     419                 :            : 
     420                 :            : static int
     421                 :      27211 : update_ufd_array(pollObject *self)
     422                 :            : {
     423                 :            :     Py_ssize_t i, pos;
     424                 :            :     PyObject *key, *value;
     425                 :      27211 :     struct pollfd *old_ufds = self->ufds;
     426                 :            : 
     427                 :      27211 :     self->ufd_len = PyDict_GET_SIZE(self->dict);
     428         [ +  - ]:      27211 :     PyMem_RESIZE(self->ufds, struct pollfd, self->ufd_len);
     429         [ -  + ]:      27211 :     if (self->ufds == NULL) {
     430                 :          0 :         self->ufds = old_ufds;
     431                 :            :         PyErr_NoMemory();
     432                 :          0 :         return 0;
     433                 :            :     }
     434                 :            : 
     435                 :      27211 :     i = pos = 0;
     436         [ +  + ]:     143971 :     while (PyDict_Next(self->dict, &pos, &key, &value)) {
     437                 :            :         assert(i < self->ufd_len);
     438                 :            :         /* Never overflow */
     439                 :     116760 :         self->ufds[i].fd = (int)PyLong_AsLong(key);
     440                 :     116760 :         self->ufds[i].events = (short)(unsigned short)PyLong_AsLong(value);
     441                 :     116760 :         i++;
     442                 :            :     }
     443                 :            :     assert(i == self->ufd_len);
     444                 :      27211 :     self->ufd_uptodate = 1;
     445                 :      27211 :     return 1;
     446                 :            : }
     447                 :            : 
     448                 :            : /*[clinic input]
     449                 :            : select.poll.register
     450                 :            : 
     451                 :            :     fd: fildes
     452                 :            :       either an integer, or an object with a fileno() method returning an int
     453                 :            :     eventmask: unsigned_short(c_default="POLLIN | POLLPRI | POLLOUT") = select.POLLIN | select.POLLPRI | select.POLLOUT
     454                 :            :       an optional bitmask describing the type of events to check for
     455                 :            :     /
     456                 :            : 
     457                 :            : Register a file descriptor with the polling object.
     458                 :            : [clinic start generated code]*/
     459                 :            : 
     460                 :            : static PyObject *
     461                 :     113777 : select_poll_register_impl(pollObject *self, int fd, unsigned short eventmask)
     462                 :            : /*[clinic end generated code: output=0dc7173c800a4a65 input=34e16cfb28d3c900]*/
     463                 :            : {
     464                 :            :     PyObject *key, *value;
     465                 :            :     int err;
     466                 :            : 
     467                 :            :     /* Add entry to the internal dictionary: the key is the
     468                 :            :        file descriptor, and the value is the event mask. */
     469                 :     113777 :     key = PyLong_FromLong(fd);
     470         [ -  + ]:     113777 :     if (key == NULL)
     471                 :          0 :         return NULL;
     472                 :     113777 :     value = PyLong_FromLong(eventmask);
     473         [ -  + ]:     113777 :     if (value == NULL) {
     474                 :          0 :         Py_DECREF(key);
     475                 :          0 :         return NULL;
     476                 :            :     }
     477                 :     113777 :     err = PyDict_SetItem(self->dict, key, value);
     478                 :     113777 :     Py_DECREF(key);
     479                 :     113777 :     Py_DECREF(value);
     480         [ -  + ]:     113777 :     if (err < 0)
     481                 :          0 :         return NULL;
     482                 :            : 
     483                 :     113777 :     self->ufd_uptodate = 0;
     484                 :            : 
     485                 :     113777 :     Py_RETURN_NONE;
     486                 :            : }
     487                 :            : 
     488                 :            : 
     489                 :            : /*[clinic input]
     490                 :            : select.poll.modify
     491                 :            : 
     492                 :            :     fd: fildes
     493                 :            :       either an integer, or an object with a fileno() method returning
     494                 :            :       an int
     495                 :            :     eventmask: unsigned_short
     496                 :            :       a bitmask describing the type of events to check for
     497                 :            :     /
     498                 :            : 
     499                 :            : Modify an already registered file descriptor.
     500                 :            : [clinic start generated code]*/
     501                 :            : 
     502                 :            : static PyObject *
     503                 :         29 : select_poll_modify_impl(pollObject *self, int fd, unsigned short eventmask)
     504                 :            : /*[clinic end generated code: output=1a7b88bf079eff17 input=a8e383df075c32cf]*/
     505                 :            : {
     506                 :            :     PyObject *key, *value;
     507                 :            :     int err;
     508                 :            : 
     509                 :            :     /* Modify registered fd */
     510                 :         29 :     key = PyLong_FromLong(fd);
     511         [ -  + ]:         29 :     if (key == NULL)
     512                 :          0 :         return NULL;
     513                 :         29 :     err = PyDict_Contains(self->dict, key);
     514         [ -  + ]:         29 :     if (err < 0) {
     515                 :          0 :         Py_DECREF(key);
     516                 :          0 :         return NULL;
     517                 :            :     }
     518         [ -  + ]:         29 :     if (err == 0) {
     519                 :          0 :         errno = ENOENT;
     520                 :          0 :         PyErr_SetFromErrno(PyExc_OSError);
     521                 :          0 :         Py_DECREF(key);
     522                 :          0 :         return NULL;
     523                 :            :     }
     524                 :         29 :     value = PyLong_FromLong(eventmask);
     525         [ -  + ]:         29 :     if (value == NULL) {
     526                 :          0 :         Py_DECREF(key);
     527                 :          0 :         return NULL;
     528                 :            :     }
     529                 :         29 :     err = PyDict_SetItem(self->dict, key, value);
     530                 :         29 :     Py_DECREF(key);
     531                 :         29 :     Py_DECREF(value);
     532         [ -  + ]:         29 :     if (err < 0)
     533                 :          0 :         return NULL;
     534                 :            : 
     535                 :         29 :     self->ufd_uptodate = 0;
     536                 :            : 
     537                 :         29 :     Py_RETURN_NONE;
     538                 :            : }
     539                 :            : 
     540                 :            : 
     541                 :            : /*[clinic input]
     542                 :            : select.poll.unregister
     543                 :            : 
     544                 :            :     fd: fildes
     545                 :            :     /
     546                 :            : 
     547                 :            : Remove a file descriptor being tracked by the polling object.
     548                 :            : [clinic start generated code]*/
     549                 :            : 
     550                 :            : static PyObject *
     551                 :       3561 : select_poll_unregister_impl(pollObject *self, int fd)
     552                 :            : /*[clinic end generated code: output=8c9f42e75e7d291b input=4b4fccc1040e79cb]*/
     553                 :            : {
     554                 :            :     PyObject *key;
     555                 :            : 
     556                 :            :     /* Check whether the fd is already in the array */
     557                 :       3561 :     key = PyLong_FromLong(fd);
     558         [ -  + ]:       3561 :     if (key == NULL)
     559                 :          0 :         return NULL;
     560                 :            : 
     561         [ +  + ]:       3561 :     if (PyDict_DelItem(self->dict, key) == -1) {
     562                 :          1 :         Py_DECREF(key);
     563                 :            :         /* This will simply raise the KeyError set by PyDict_DelItem
     564                 :            :            if the file descriptor isn't registered. */
     565                 :          1 :         return NULL;
     566                 :            :     }
     567                 :            : 
     568                 :       3560 :     Py_DECREF(key);
     569                 :       3560 :     self->ufd_uptodate = 0;
     570                 :            : 
     571                 :       3560 :     Py_RETURN_NONE;
     572                 :            : }
     573                 :            : 
     574                 :            : /*[clinic input]
     575                 :            : select.poll.poll
     576                 :            : 
     577                 :            :     timeout as timeout_obj: object = None
     578                 :            :       The maximum time to wait in milliseconds, or else None (or a negative
     579                 :            :       value) to wait indefinitely.
     580                 :            :     /
     581                 :            : 
     582                 :            : Polls the set of registered file descriptors.
     583                 :            : 
     584                 :            : Returns a list containing any descriptors that have events or errors to
     585                 :            : report, as a list of (fd, event) 2-tuples.
     586                 :            : [clinic start generated code]*/
     587                 :            : 
     588                 :            : static PyObject *
     589                 :      49941 : select_poll_poll_impl(pollObject *self, PyObject *timeout_obj)
     590                 :            : /*[clinic end generated code: output=876e837d193ed7e4 input=c2f6953ec45e5622]*/
     591                 :            : {
     592                 :      49941 :     PyObject *result_list = NULL;
     593                 :            :     int poll_result, i, j;
     594                 :      49941 :     PyObject *value = NULL, *num = NULL;
     595                 :      49941 :     _PyTime_t timeout = -1, ms = -1, deadline = 0;
     596                 :      49941 :     int async_err = 0;
     597                 :            : 
     598         [ +  + ]:      49941 :     if (timeout_obj != Py_None) {
     599         [ +  + ]:      20094 :         if (_PyTime_FromMillisecondsObject(&timeout, timeout_obj,
     600                 :            :                                            _PyTime_ROUND_TIMEOUT) < 0) {
     601         [ -  + ]:          1 :             if (PyErr_ExceptionMatches(PyExc_TypeError)) {
     602                 :          0 :                 PyErr_SetString(PyExc_TypeError,
     603                 :            :                                 "timeout must be an integer or None");
     604                 :            :             }
     605                 :          1 :             return NULL;
     606                 :            :         }
     607                 :            : 
     608                 :      20093 :         ms = _PyTime_AsMilliseconds(timeout, _PyTime_ROUND_TIMEOUT);
     609   [ +  -  +  + ]:      20093 :         if (ms < INT_MIN || ms > INT_MAX) {
     610                 :          2 :             PyErr_SetString(PyExc_OverflowError, "timeout is too large");
     611                 :          2 :             return NULL;
     612                 :            :         }
     613                 :            : 
     614         [ +  + ]:      20091 :         if (timeout >= 0) {
     615                 :      20076 :             deadline = _PyDeadline_Init(timeout);
     616                 :            :         }
     617                 :            :     }
     618                 :            : 
     619                 :            :     /* On some OSes, typically BSD-based ones, the timeout parameter of the
     620                 :            :        poll() syscall, when negative, must be exactly INFTIM, where defined,
     621                 :            :        or -1. See issue 31334. */
     622         [ +  + ]:      49938 :     if (ms < 0) {
     623                 :            : #ifdef INFTIM
     624                 :            :         ms = INFTIM;
     625                 :            : #else
     626                 :      29862 :         ms = -1;
     627                 :            : #endif
     628                 :            :     }
     629                 :            : 
     630                 :            :     /* Avoid concurrent poll() invocation, issue 8865 */
     631         [ +  + ]:      49938 :     if (self->poll_running) {
     632                 :          1 :         PyErr_SetString(PyExc_RuntimeError,
     633                 :            :                         "concurrent poll() invocation");
     634                 :          1 :         return NULL;
     635                 :            :     }
     636                 :            : 
     637                 :            :     /* Ensure the ufd array is up to date */
     638         [ +  + ]:      49937 :     if (!self->ufd_uptodate)
     639         [ -  + ]:      27211 :         if (update_ufd_array(self) == 0)
     640                 :          0 :             return NULL;
     641                 :            : 
     642                 :      49937 :     self->poll_running = 1;
     643                 :            : 
     644                 :            :     /* call poll() */
     645                 :      49937 :     async_err = 0;
     646                 :            :     do {
     647                 :      49953 :         Py_BEGIN_ALLOW_THREADS
     648                 :      49953 :         errno = 0;
     649                 :      49953 :         poll_result = poll(self->ufds, self->ufd_len, (int)ms);
     650                 :      49953 :         Py_END_ALLOW_THREADS
     651                 :            : 
     652         [ +  + ]:      49953 :         if (errno != EINTR)
     653                 :      49936 :             break;
     654                 :            : 
     655                 :            :         /* poll() was interrupted by a signal */
     656         [ +  + ]:         17 :         if (PyErr_CheckSignals()) {
     657                 :          1 :             async_err = 1;
     658                 :          1 :             break;
     659                 :            :         }
     660                 :            : 
     661         [ +  + ]:         16 :         if (timeout >= 0) {
     662                 :          5 :             timeout = _PyDeadline_Get(deadline);
     663         [ -  + ]:          5 :             if (timeout < 0) {
     664                 :          0 :                 poll_result = 0;
     665                 :          0 :                 break;
     666                 :            :             }
     667                 :          5 :             ms = _PyTime_AsMilliseconds(timeout, _PyTime_ROUND_CEILING);
     668                 :            :             /* retry poll() with the recomputed timeout */
     669                 :            :         }
     670                 :            :     } while (1);
     671                 :            : 
     672                 :      49937 :     self->poll_running = 0;
     673                 :            : 
     674         [ +  + ]:      49937 :     if (poll_result < 0) {
     675         [ -  + ]:          1 :         if (!async_err)
     676                 :          0 :             PyErr_SetFromErrno(PyExc_OSError);
     677                 :          1 :         return NULL;
     678                 :            :     }
     679                 :            : 
     680                 :            :     /* build the result list */
     681                 :            : 
     682                 :      49936 :     result_list = PyList_New(poll_result);
     683         [ -  + ]:      49936 :     if (!result_list)
     684                 :          0 :         return NULL;
     685                 :            : 
     686         [ +  + ]:     118714 :     for (i = 0, j = 0; j < poll_result; j++) {
     687                 :            :         /* skip to the next fired descriptor */
     688         [ +  + ]:     125548 :         while (!self->ufds[i].revents) {
     689                 :      56770 :             i++;
     690                 :            :         }
     691                 :            :         /* if we hit a NULL return, set value to NULL
     692                 :            :            and break out of loop; code at end will
     693                 :            :            clean up result_list */
     694                 :      68778 :         value = PyTuple_New(2);
     695         [ -  + ]:      68778 :         if (value == NULL)
     696                 :          0 :             goto error;
     697                 :      68778 :         num = PyLong_FromLong(self->ufds[i].fd);
     698         [ -  + ]:      68778 :         if (num == NULL) {
     699                 :          0 :             Py_DECREF(value);
     700                 :          0 :             goto error;
     701                 :            :         }
     702                 :      68778 :         PyTuple_SET_ITEM(value, 0, num);
     703                 :            : 
     704                 :            :         /* The &0xffff is a workaround for AIX.  'revents'
     705                 :            :            is a 16-bit short, and IBM assigned POLLNVAL
     706                 :            :            to be 0x8000, so the conversion to int results
     707                 :            :            in a negative number. See SF bug #923315. */
     708                 :      68778 :         num = PyLong_FromLong(self->ufds[i].revents & 0xffff);
     709         [ -  + ]:      68778 :         if (num == NULL) {
     710                 :          0 :             Py_DECREF(value);
     711                 :          0 :             goto error;
     712                 :            :         }
     713                 :      68778 :         PyTuple_SET_ITEM(value, 1, num);
     714                 :      68778 :         PyList_SET_ITEM(result_list, j, value);
     715                 :      68778 :         i++;
     716                 :            :     }
     717                 :      49936 :     return result_list;
     718                 :            : 
     719                 :          0 :   error:
     720                 :          0 :     Py_DECREF(result_list);
     721                 :          0 :     return NULL;
     722                 :            : }
     723                 :            : 
     724                 :            : static pollObject *
     725                 :      25411 : newPollObject(PyObject *module)
     726                 :            : {
     727                 :            :     pollObject *self;
     728                 :      25411 :     self = PyObject_New(pollObject, get_select_state(module)->poll_Type);
     729         [ -  + ]:      25411 :     if (self == NULL)
     730                 :          0 :         return NULL;
     731                 :            :     /* ufd_uptodate is a Boolean, denoting whether the
     732                 :            :        array pointed to by ufds matches the contents of the dictionary. */
     733                 :      25411 :     self->ufd_uptodate = 0;
     734                 :      25411 :     self->ufds = NULL;
     735                 :      25411 :     self->poll_running = 0;
     736                 :      25411 :     self->dict = PyDict_New();
     737         [ -  + ]:      25411 :     if (self->dict == NULL) {
     738                 :          0 :         Py_DECREF(self);
     739                 :          0 :         return NULL;
     740                 :            :     }
     741                 :      25411 :     return self;
     742                 :            : }
     743                 :            : 
     744                 :            : static void
     745                 :      25411 : poll_dealloc(pollObject *self)
     746                 :            : {
     747                 :      25411 :     PyObject* type = (PyObject *)Py_TYPE(self);
     748         [ +  + ]:      25411 :     if (self->ufds != NULL)
     749                 :      25363 :         PyMem_Free(self->ufds);
     750                 :      25411 :     Py_XDECREF(self->dict);
     751                 :      25411 :     PyObject_Free(self);
     752                 :      25411 :     Py_DECREF(type);
     753                 :      25411 : }
     754                 :            : 
     755                 :            : 
     756                 :            : #ifdef HAVE_SYS_DEVPOLL_H
     757                 :            : static PyMethodDef devpoll_methods[];
     758                 :            : 
     759                 :            : typedef struct {
     760                 :            :     PyObject_HEAD
     761                 :            :     int fd_devpoll;
     762                 :            :     int max_n_fds;
     763                 :            :     int n_fds;
     764                 :            :     struct pollfd *fds;
     765                 :            : } devpollObject;
     766                 :            : 
     767                 :            : static PyObject *
     768                 :            : devpoll_err_closed(void)
     769                 :            : {
     770                 :            :     PyErr_SetString(PyExc_ValueError, "I/O operation on closed devpoll object");
     771                 :            :     return NULL;
     772                 :            : }
     773                 :            : 
     774                 :            : static int devpoll_flush(devpollObject *self)
     775                 :            : {
     776                 :            :     int size, n;
     777                 :            : 
     778                 :            :     if (!self->n_fds) return 0;
     779                 :            : 
     780                 :            :     size = sizeof(struct pollfd)*self->n_fds;
     781                 :            :     self->n_fds = 0;
     782                 :            : 
     783                 :            :     n = _Py_write(self->fd_devpoll, self->fds, size);
     784                 :            :     if (n == -1)
     785                 :            :         return -1;
     786                 :            : 
     787                 :            :     if (n < size) {
     788                 :            :         /*
     789                 :            :         ** Data writed to /dev/poll is a binary data structure. It is not
     790                 :            :         ** clear what to do if a partial write occurred. For now, raise
     791                 :            :         ** an exception and see if we actually found this problem in
     792                 :            :         ** the wild.
     793                 :            :         ** See http://bugs.python.org/issue6397.
     794                 :            :         */
     795                 :            :         PyErr_Format(PyExc_OSError, "failed to write all pollfds. "
     796                 :            :                 "Please, report at http://bugs.python.org/. "
     797                 :            :                 "Data to report: Size tried: %d, actual size written: %d.",
     798                 :            :                 size, n);
     799                 :            :         return -1;
     800                 :            :     }
     801                 :            :     return 0;
     802                 :            : }
     803                 :            : 
     804                 :            : static PyObject *
     805                 :            : internal_devpoll_register(devpollObject *self, int fd,
     806                 :            :                           unsigned short events, int remove)
     807                 :            : {
     808                 :            :     if (self->fd_devpoll < 0)
     809                 :            :         return devpoll_err_closed();
     810                 :            : 
     811                 :            :     if (remove) {
     812                 :            :         self->fds[self->n_fds].fd = fd;
     813                 :            :         self->fds[self->n_fds].events = POLLREMOVE;
     814                 :            : 
     815                 :            :         if (++self->n_fds == self->max_n_fds) {
     816                 :            :             if (devpoll_flush(self))
     817                 :            :                 return NULL;
     818                 :            :         }
     819                 :            :     }
     820                 :            : 
     821                 :            :     self->fds[self->n_fds].fd = fd;
     822                 :            :     self->fds[self->n_fds].events = (signed short)events;
     823                 :            : 
     824                 :            :     if (++self->n_fds == self->max_n_fds) {
     825                 :            :         if (devpoll_flush(self))
     826                 :            :             return NULL;
     827                 :            :     }
     828                 :            : 
     829                 :            :     Py_RETURN_NONE;
     830                 :            : }
     831                 :            : 
     832                 :            : /*[clinic input]
     833                 :            : select.devpoll.register
     834                 :            : 
     835                 :            :     fd: fildes
     836                 :            :         either an integer, or an object with a fileno() method returning
     837                 :            :         an int
     838                 :            :     eventmask: unsigned_short(c_default="POLLIN | POLLPRI | POLLOUT") = select.POLLIN | select.POLLPRI | select.POLLOUT
     839                 :            :         an optional bitmask describing the type of events to check for
     840                 :            :     /
     841                 :            : 
     842                 :            : Register a file descriptor with the polling object.
     843                 :            : [clinic start generated code]*/
     844                 :            : 
     845                 :            : static PyObject *
     846                 :            : select_devpoll_register_impl(devpollObject *self, int fd,
     847                 :            :                              unsigned short eventmask)
     848                 :            : /*[clinic end generated code: output=6e07fe8b74abba0c input=22006fabe9567522]*/
     849                 :            : {
     850                 :            :     return internal_devpoll_register(self, fd, eventmask, 0);
     851                 :            : }
     852                 :            : 
     853                 :            : /*[clinic input]
     854                 :            : select.devpoll.modify
     855                 :            : 
     856                 :            :     fd: fildes
     857                 :            :         either an integer, or an object with a fileno() method returning
     858                 :            :         an int
     859                 :            :     eventmask: unsigned_short(c_default="POLLIN | POLLPRI | POLLOUT") = select.POLLIN | select.POLLPRI | select.POLLOUT
     860                 :            :         an optional bitmask describing the type of events to check for
     861                 :            :     /
     862                 :            : 
     863                 :            : Modify a possible already registered file descriptor.
     864                 :            : [clinic start generated code]*/
     865                 :            : 
     866                 :            : static PyObject *
     867                 :            : select_devpoll_modify_impl(devpollObject *self, int fd,
     868                 :            :                            unsigned short eventmask)
     869                 :            : /*[clinic end generated code: output=bc2e6d23aaff98b4 input=09fa335db7cdc09e]*/
     870                 :            : {
     871                 :            :     return internal_devpoll_register(self, fd, eventmask, 1);
     872                 :            : }
     873                 :            : 
     874                 :            : /*[clinic input]
     875                 :            : select.devpoll.unregister
     876                 :            : 
     877                 :            :     fd: fildes
     878                 :            :     /
     879                 :            : 
     880                 :            : Remove a file descriptor being tracked by the polling object.
     881                 :            : [clinic start generated code]*/
     882                 :            : 
     883                 :            : static PyObject *
     884                 :            : select_devpoll_unregister_impl(devpollObject *self, int fd)
     885                 :            : /*[clinic end generated code: output=95519ffa0c7d43fe input=b4ea42a4442fd467]*/
     886                 :            : {
     887                 :            :     if (self->fd_devpoll < 0)
     888                 :            :         return devpoll_err_closed();
     889                 :            : 
     890                 :            :     self->fds[self->n_fds].fd = fd;
     891                 :            :     self->fds[self->n_fds].events = POLLREMOVE;
     892                 :            : 
     893                 :            :     if (++self->n_fds == self->max_n_fds) {
     894                 :            :         if (devpoll_flush(self))
     895                 :            :             return NULL;
     896                 :            :     }
     897                 :            : 
     898                 :            :     Py_RETURN_NONE;
     899                 :            : }
     900                 :            : 
     901                 :            : /*[clinic input]
     902                 :            : select.devpoll.poll
     903                 :            :     timeout as timeout_obj: object = None
     904                 :            :       The maximum time to wait in milliseconds, or else None (or a negative
     905                 :            :       value) to wait indefinitely.
     906                 :            :     /
     907                 :            : 
     908                 :            : Polls the set of registered file descriptors.
     909                 :            : 
     910                 :            : Returns a list containing any descriptors that have events or errors to
     911                 :            : report, as a list of (fd, event) 2-tuples.
     912                 :            : [clinic start generated code]*/
     913                 :            : 
     914                 :            : static PyObject *
     915                 :            : select_devpoll_poll_impl(devpollObject *self, PyObject *timeout_obj)
     916                 :            : /*[clinic end generated code: output=2654e5457cca0b3c input=3c3f0a355ec2bedb]*/
     917                 :            : {
     918                 :            :     struct dvpoll dvp;
     919                 :            :     PyObject *result_list = NULL;
     920                 :            :     int poll_result, i;
     921                 :            :     PyObject *value, *num1, *num2;
     922                 :            :     _PyTime_t timeout, ms, deadline = 0;
     923                 :            : 
     924                 :            :     if (self->fd_devpoll < 0)
     925                 :            :         return devpoll_err_closed();
     926                 :            : 
     927                 :            :     /* Check values for timeout */
     928                 :            :     if (timeout_obj == Py_None) {
     929                 :            :         timeout = -1;
     930                 :            :         ms = -1;
     931                 :            :     }
     932                 :            :     else {
     933                 :            :         if (_PyTime_FromMillisecondsObject(&timeout, timeout_obj,
     934                 :            :                                            _PyTime_ROUND_TIMEOUT) < 0) {
     935                 :            :             if (PyErr_ExceptionMatches(PyExc_TypeError)) {
     936                 :            :                 PyErr_SetString(PyExc_TypeError,
     937                 :            :                                 "timeout must be an integer or None");
     938                 :            :             }
     939                 :            :             return NULL;
     940                 :            :         }
     941                 :            : 
     942                 :            :         ms = _PyTime_AsMilliseconds(timeout, _PyTime_ROUND_TIMEOUT);
     943                 :            :         if (ms < -1 || ms > INT_MAX) {
     944                 :            :             PyErr_SetString(PyExc_OverflowError, "timeout is too large");
     945                 :            :             return NULL;
     946                 :            :         }
     947                 :            :     }
     948                 :            : 
     949                 :            :     if (devpoll_flush(self))
     950                 :            :         return NULL;
     951                 :            : 
     952                 :            :     dvp.dp_fds = self->fds;
     953                 :            :     dvp.dp_nfds = self->max_n_fds;
     954                 :            :     dvp.dp_timeout = (int)ms;
     955                 :            : 
     956                 :            :     if (timeout >= 0) {
     957                 :            :         deadline = _PyDeadline_Init(timeout);
     958                 :            :     }
     959                 :            : 
     960                 :            :     do {
     961                 :            :         /* call devpoll() */
     962                 :            :         Py_BEGIN_ALLOW_THREADS
     963                 :            :         errno = 0;
     964                 :            :         poll_result = ioctl(self->fd_devpoll, DP_POLL, &dvp);
     965                 :            :         Py_END_ALLOW_THREADS
     966                 :            : 
     967                 :            :         if (errno != EINTR)
     968                 :            :             break;
     969                 :            : 
     970                 :            :         /* devpoll() was interrupted by a signal */
     971                 :            :         if (PyErr_CheckSignals())
     972                 :            :             return NULL;
     973                 :            : 
     974                 :            :         if (timeout >= 0) {
     975                 :            :             timeout = _PyDeadline_Get(deadline);
     976                 :            :             if (timeout < 0) {
     977                 :            :                 poll_result = 0;
     978                 :            :                 break;
     979                 :            :             }
     980                 :            :             ms = _PyTime_AsMilliseconds(timeout, _PyTime_ROUND_CEILING);
     981                 :            :             dvp.dp_timeout = (int)ms;
     982                 :            :             /* retry devpoll() with the recomputed timeout */
     983                 :            :         }
     984                 :            :     } while (1);
     985                 :            : 
     986                 :            :     if (poll_result < 0) {
     987                 :            :         PyErr_SetFromErrno(PyExc_OSError);
     988                 :            :         return NULL;
     989                 :            :     }
     990                 :            : 
     991                 :            :     /* build the result list */
     992                 :            :     result_list = PyList_New(poll_result);
     993                 :            :     if (!result_list)
     994                 :            :         return NULL;
     995                 :            : 
     996                 :            :     for (i = 0; i < poll_result; i++) {
     997                 :            :         num1 = PyLong_FromLong(self->fds[i].fd);
     998                 :            :         num2 = PyLong_FromLong(self->fds[i].revents);
     999                 :            :         if ((num1 == NULL) || (num2 == NULL)) {
    1000                 :            :             Py_XDECREF(num1);
    1001                 :            :             Py_XDECREF(num2);
    1002                 :            :             goto error;
    1003                 :            :         }
    1004                 :            :         value = PyTuple_Pack(2, num1, num2);
    1005                 :            :         Py_DECREF(num1);
    1006                 :            :         Py_DECREF(num2);
    1007                 :            :         if (value == NULL)
    1008                 :            :             goto error;
    1009                 :            :         PyList_SET_ITEM(result_list, i, value);
    1010                 :            :     }
    1011                 :            : 
    1012                 :            :     return result_list;
    1013                 :            : 
    1014                 :            :   error:
    1015                 :            :     Py_DECREF(result_list);
    1016                 :            :     return NULL;
    1017                 :            : }
    1018                 :            : 
    1019                 :            : static int
    1020                 :            : devpoll_internal_close(devpollObject *self)
    1021                 :            : {
    1022                 :            :     int save_errno = 0;
    1023                 :            :     if (self->fd_devpoll >= 0) {
    1024                 :            :         int fd = self->fd_devpoll;
    1025                 :            :         self->fd_devpoll = -1;
    1026                 :            :         Py_BEGIN_ALLOW_THREADS
    1027                 :            :         if (close(fd) < 0)
    1028                 :            :             save_errno = errno;
    1029                 :            :         Py_END_ALLOW_THREADS
    1030                 :            :     }
    1031                 :            :     return save_errno;
    1032                 :            : }
    1033                 :            : 
    1034                 :            : /*[clinic input]
    1035                 :            : select.devpoll.close
    1036                 :            : 
    1037                 :            : Close the devpoll file descriptor.
    1038                 :            : 
    1039                 :            : Further operations on the devpoll object will raise an exception.
    1040                 :            : [clinic start generated code]*/
    1041                 :            : 
    1042                 :            : static PyObject *
    1043                 :            : select_devpoll_close_impl(devpollObject *self)
    1044                 :            : /*[clinic end generated code: output=26b355bd6429f21b input=6273c30f5560a99b]*/
    1045                 :            : {
    1046                 :            :     errno = devpoll_internal_close(self);
    1047                 :            :     if (errno < 0) {
    1048                 :            :         PyErr_SetFromErrno(PyExc_OSError);
    1049                 :            :         return NULL;
    1050                 :            :     }
    1051                 :            :     Py_RETURN_NONE;
    1052                 :            : }
    1053                 :            : 
    1054                 :            : static PyObject*
    1055                 :            : devpoll_get_closed(devpollObject *self, void *Py_UNUSED(ignored))
    1056                 :            : {
    1057                 :            :     if (self->fd_devpoll < 0)
    1058                 :            :         Py_RETURN_TRUE;
    1059                 :            :     else
    1060                 :            :         Py_RETURN_FALSE;
    1061                 :            : }
    1062                 :            : 
    1063                 :            : /*[clinic input]
    1064                 :            : select.devpoll.fileno
    1065                 :            : 
    1066                 :            : Return the file descriptor.
    1067                 :            : [clinic start generated code]*/
    1068                 :            : 
    1069                 :            : static PyObject *
    1070                 :            : select_devpoll_fileno_impl(devpollObject *self)
    1071                 :            : /*[clinic end generated code: output=26920929f8d292f4 input=ef15331ebde6c368]*/
    1072                 :            : {
    1073                 :            :     if (self->fd_devpoll < 0)
    1074                 :            :         return devpoll_err_closed();
    1075                 :            :     return PyLong_FromLong(self->fd_devpoll);
    1076                 :            : }
    1077                 :            : 
    1078                 :            : static PyGetSetDef devpoll_getsetlist[] = {
    1079                 :            :     {"closed", (getter)devpoll_get_closed, NULL,
    1080                 :            :      "True if the devpoll object is closed"},
    1081                 :            :     {0},
    1082                 :            : };
    1083                 :            : 
    1084                 :            : static devpollObject *
    1085                 :            : newDevPollObject(PyObject *module)
    1086                 :            : {
    1087                 :            :     devpollObject *self;
    1088                 :            :     int fd_devpoll, limit_result;
    1089                 :            :     struct pollfd *fds;
    1090                 :            :     struct rlimit limit;
    1091                 :            : 
    1092                 :            :     /*
    1093                 :            :     ** If we try to process more that getrlimit()
    1094                 :            :     ** fds, the kernel will give an error, so
    1095                 :            :     ** we set the limit here. It is a dynamic
    1096                 :            :     ** value, because we can change rlimit() anytime.
    1097                 :            :     */
    1098                 :            :     limit_result = getrlimit(RLIMIT_NOFILE, &limit);
    1099                 :            :     if (limit_result == -1) {
    1100                 :            :         PyErr_SetFromErrno(PyExc_OSError);
    1101                 :            :         return NULL;
    1102                 :            :     }
    1103                 :            : 
    1104                 :            :     fd_devpoll = _Py_open("/dev/poll", O_RDWR);
    1105                 :            :     if (fd_devpoll == -1)
    1106                 :            :         return NULL;
    1107                 :            : 
    1108                 :            :     fds = PyMem_NEW(struct pollfd, limit.rlim_cur);
    1109                 :            :     if (fds == NULL) {
    1110                 :            :         close(fd_devpoll);
    1111                 :            :         PyErr_NoMemory();
    1112                 :            :         return NULL;
    1113                 :            :     }
    1114                 :            : 
    1115                 :            :     self = PyObject_New(devpollObject, get_select_state(module)->devpoll_Type);
    1116                 :            :     if (self == NULL) {
    1117                 :            :         close(fd_devpoll);
    1118                 :            :         PyMem_Free(fds);
    1119                 :            :         return NULL;
    1120                 :            :     }
    1121                 :            :     self->fd_devpoll = fd_devpoll;
    1122                 :            :     self->max_n_fds = limit.rlim_cur;
    1123                 :            :     self->n_fds = 0;
    1124                 :            :     self->fds = fds;
    1125                 :            : 
    1126                 :            :     return self;
    1127                 :            : }
    1128                 :            : 
    1129                 :            : static void
    1130                 :            : devpoll_dealloc(devpollObject *self)
    1131                 :            : {
    1132                 :            :     PyObject *type = (PyObject *)Py_TYPE(self);
    1133                 :            :     (void)devpoll_internal_close(self);
    1134                 :            :     PyMem_Free(self->fds);
    1135                 :            :     PyObject_Free(self);
    1136                 :            :     Py_DECREF(type);
    1137                 :            : }
    1138                 :            : 
    1139                 :            : static PyType_Slot devpoll_Type_slots[] = {
    1140                 :            :     {Py_tp_dealloc, devpoll_dealloc},
    1141                 :            :     {Py_tp_getset, devpoll_getsetlist},
    1142                 :            :     {Py_tp_methods, devpoll_methods},
    1143                 :            :     {0, 0},
    1144                 :            : };
    1145                 :            : 
    1146                 :            : static PyType_Spec devpoll_Type_spec = {
    1147                 :            :     "select.devpoll",
    1148                 :            :     sizeof(devpollObject),
    1149                 :            :     0,
    1150                 :            :     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION,
    1151                 :            :     devpoll_Type_slots
    1152                 :            : };
    1153                 :            : 
    1154                 :            : #endif  /* HAVE_SYS_DEVPOLL_H */
    1155                 :            : 
    1156                 :            : 
    1157                 :            : /*[clinic input]
    1158                 :            : select.poll
    1159                 :            : 
    1160                 :            : Returns a polling object.
    1161                 :            : 
    1162                 :            : This object supports registering and unregistering file descriptors, and then
    1163                 :            : polling them for I/O events.
    1164                 :            : [clinic start generated code]*/
    1165                 :            : 
    1166                 :            : static PyObject *
    1167                 :      25411 : select_poll_impl(PyObject *module)
    1168                 :            : /*[clinic end generated code: output=16a665a4e1d228c5 input=3f877909d5696bbf]*/
    1169                 :            : {
    1170                 :      25411 :     return (PyObject *)newPollObject(module);
    1171                 :            : }
    1172                 :            : 
    1173                 :            : #ifdef HAVE_SYS_DEVPOLL_H
    1174                 :            : 
    1175                 :            : /*[clinic input]
    1176                 :            : select.devpoll
    1177                 :            : 
    1178                 :            : Returns a polling object.
    1179                 :            : 
    1180                 :            : This object supports registering and unregistering file descriptors, and then
    1181                 :            : polling them for I/O events.
    1182                 :            : [clinic start generated code]*/
    1183                 :            : 
    1184                 :            : static PyObject *
    1185                 :            : select_devpoll_impl(PyObject *module)
    1186                 :            : /*[clinic end generated code: output=ea9213cc87fd9581 input=53a1af94564f00a3]*/
    1187                 :            : {
    1188                 :            :     return (PyObject *)newDevPollObject(module);
    1189                 :            : }
    1190                 :            : #endif
    1191                 :            : 
    1192                 :            : 
    1193                 :            : #ifdef __APPLE__
    1194                 :            : /*
    1195                 :            :  * On some systems poll() sets errno on invalid file descriptors. We test
    1196                 :            :  * for this at runtime because this bug may be fixed or introduced between
    1197                 :            :  * OS releases.
    1198                 :            :  */
    1199                 :            : static int select_have_broken_poll(void)
    1200                 :            : {
    1201                 :            :     int poll_test;
    1202                 :            :     int filedes[2];
    1203                 :            : 
    1204                 :            :     struct pollfd poll_struct = { 0, POLLIN|POLLPRI|POLLOUT, 0 };
    1205                 :            : 
    1206                 :            :     /* Create a file descriptor to make invalid */
    1207                 :            :     if (pipe(filedes) < 0) {
    1208                 :            :         return 1;
    1209                 :            :     }
    1210                 :            :     poll_struct.fd = filedes[0];
    1211                 :            :     close(filedes[0]);
    1212                 :            :     close(filedes[1]);
    1213                 :            :     poll_test = poll(&poll_struct, 1, 0);
    1214                 :            :     if (poll_test < 0) {
    1215                 :            :         return 1;
    1216                 :            :     } else if (poll_test == 0 && poll_struct.revents != POLLNVAL) {
    1217                 :            :         return 1;
    1218                 :            :     }
    1219                 :            :     return 0;
    1220                 :            : }
    1221                 :            : #endif /* __APPLE__ */
    1222                 :            : 
    1223                 :            : #endif /* HAVE_POLL */
    1224                 :            : 
    1225                 :            : #ifdef HAVE_EPOLL
    1226                 :            : /* **************************************************************************
    1227                 :            :  *                      epoll interface for Linux 2.6
    1228                 :            :  *
    1229                 :            :  * Written by Christian Heimes
    1230                 :            :  * Inspired by Twisted's _epoll.pyx and select.poll()
    1231                 :            :  */
    1232                 :            : 
    1233                 :            : #ifdef HAVE_SYS_EPOLL_H
    1234                 :            : #include <sys/epoll.h>
    1235                 :            : #endif
    1236                 :            : 
    1237                 :            : typedef struct {
    1238                 :            :     PyObject_HEAD
    1239                 :            :     SOCKET epfd;                        /* epoll control file descriptor */
    1240                 :            : } pyEpoll_Object;
    1241                 :            : 
    1242                 :            : static PyObject *
    1243                 :          7 : pyepoll_err_closed(void)
    1244                 :            : {
    1245                 :          7 :     PyErr_SetString(PyExc_ValueError, "I/O operation on closed epoll object");
    1246                 :          7 :     return NULL;
    1247                 :            : }
    1248                 :            : 
    1249                 :            : static int
    1250                 :       5061 : pyepoll_internal_close(pyEpoll_Object *self)
    1251                 :            : {
    1252                 :       5061 :     int save_errno = 0;
    1253         [ +  + ]:       5061 :     if (self->epfd >= 0) {
    1254                 :       2534 :         int epfd = self->epfd;
    1255                 :       2534 :         self->epfd = -1;
    1256                 :       2534 :         Py_BEGIN_ALLOW_THREADS
    1257         [ +  + ]:       2534 :         if (close(epfd) < 0)
    1258                 :          1 :             save_errno = errno;
    1259                 :       2534 :         Py_END_ALLOW_THREADS
    1260                 :            :     }
    1261                 :       5061 :     return save_errno;
    1262                 :            : }
    1263                 :            : 
    1264                 :            : static PyObject *
    1265                 :       2534 : newPyEpoll_Object(PyTypeObject *type, int sizehint, SOCKET fd)
    1266                 :            : {
    1267                 :            :     pyEpoll_Object *self;
    1268                 :            :     assert(type != NULL);
    1269                 :       2534 :     allocfunc epoll_alloc = PyType_GetSlot(type, Py_tp_alloc);
    1270                 :            :     assert(epoll_alloc != NULL);
    1271                 :       2534 :     self = (pyEpoll_Object *) epoll_alloc(type, 0);
    1272         [ -  + ]:       2534 :     if (self == NULL)
    1273                 :          0 :         return NULL;
    1274                 :            : 
    1275         [ +  + ]:       2534 :     if (fd == -1) {
    1276                 :       2533 :         Py_BEGIN_ALLOW_THREADS
    1277                 :            : #ifdef HAVE_EPOLL_CREATE1
    1278                 :       2533 :         self->epfd = epoll_create1(EPOLL_CLOEXEC);
    1279                 :            : #else
    1280                 :            :         self->epfd = epoll_create(sizehint);
    1281                 :            : #endif
    1282                 :       2533 :         Py_END_ALLOW_THREADS
    1283                 :            :     }
    1284                 :            :     else {
    1285                 :          1 :         self->epfd = fd;
    1286                 :            :     }
    1287         [ -  + ]:       2534 :     if (self->epfd < 0) {
    1288                 :          0 :         Py_DECREF(self);
    1289                 :          0 :         PyErr_SetFromErrno(PyExc_OSError);
    1290                 :          0 :         return NULL;
    1291                 :            :     }
    1292                 :            : 
    1293                 :            : #ifndef HAVE_EPOLL_CREATE1
    1294                 :            :     if (fd == -1 && _Py_set_inheritable(self->epfd, 0, NULL) < 0) {
    1295                 :            :         Py_DECREF(self);
    1296                 :            :         return NULL;
    1297                 :            :     }
    1298                 :            : #endif
    1299                 :            : 
    1300                 :       2534 :     return (PyObject *)self;
    1301                 :            : }
    1302                 :            : 
    1303                 :            : 
    1304                 :            : /*[clinic input]
    1305                 :            : @classmethod
    1306                 :            : select.epoll.__new__
    1307                 :            : 
    1308                 :            :     sizehint: int = -1
    1309                 :            :       The expected number of events to be registered.  It must be positive,
    1310                 :            :       or -1 to use the default.  It is only used on older systems where
    1311                 :            :       epoll_create1() is not available; otherwise it has no effect (though its
    1312                 :            :       value is still checked).
    1313                 :            :     flags: int = 0
    1314                 :            :       Deprecated and completely ignored.  However, when supplied, its value
    1315                 :            :       must be 0 or select.EPOLL_CLOEXEC, otherwise OSError is raised.
    1316                 :            : 
    1317                 :            : Returns an epolling object.
    1318                 :            : [clinic start generated code]*/
    1319                 :            : 
    1320                 :            : static PyObject *
    1321                 :       2538 : select_epoll_impl(PyTypeObject *type, int sizehint, int flags)
    1322                 :            : /*[clinic end generated code: output=c87404e705013bb5 input=303e3295e7975e43]*/
    1323                 :            : {
    1324         [ +  + ]:       2538 :     if (sizehint == -1) {
    1325                 :       2526 :         sizehint = FD_SETSIZE - 1;
    1326                 :            :     }
    1327         [ +  + ]:         12 :     else if (sizehint <= 0) {
    1328                 :          4 :         PyErr_SetString(PyExc_ValueError, "negative sizehint");
    1329                 :          4 :         return NULL;
    1330                 :            :     }
    1331                 :            : 
    1332                 :            : #ifdef HAVE_EPOLL_CREATE1
    1333   [ +  +  +  + ]:       2534 :     if (flags && flags != EPOLL_CLOEXEC) {
    1334                 :          1 :         PyErr_SetString(PyExc_OSError, "invalid flags");
    1335                 :          1 :         return NULL;
    1336                 :            :     }
    1337                 :            : #endif
    1338                 :            : 
    1339                 :       2533 :     return newPyEpoll_Object(type, sizehint, -1);
    1340                 :            : }
    1341                 :            : 
    1342                 :            : 
    1343                 :            : static void
    1344                 :       2534 : pyepoll_dealloc(pyEpoll_Object *self)
    1345                 :            : {
    1346                 :       2534 :     PyTypeObject* type = Py_TYPE(self);
    1347                 :       2534 :     (void)pyepoll_internal_close(self);
    1348                 :       2534 :     freefunc epoll_free = PyType_GetSlot(type, Py_tp_free);
    1349                 :       2534 :     epoll_free((PyObject *)self);
    1350                 :       2534 :     Py_DECREF((PyObject *)type);
    1351                 :       2534 : }
    1352                 :            : 
    1353                 :            : /*[clinic input]
    1354                 :            : select.epoll.close
    1355                 :            : 
    1356                 :            : Close the epoll control file descriptor.
    1357                 :            : 
    1358                 :            : Further operations on the epoll object will raise an exception.
    1359                 :            : [clinic start generated code]*/
    1360                 :            : 
    1361                 :            : static PyObject *
    1362                 :       2527 : select_epoll_close_impl(pyEpoll_Object *self)
    1363                 :            : /*[clinic end generated code: output=ee2144c446a1a435 input=ca6c66ba5a736bfd]*/
    1364                 :            : {
    1365                 :       2527 :     errno = pyepoll_internal_close(self);
    1366         [ -  + ]:       2527 :     if (errno < 0) {
    1367                 :          0 :         PyErr_SetFromErrno(PyExc_OSError);
    1368                 :          0 :         return NULL;
    1369                 :            :     }
    1370                 :       2527 :     Py_RETURN_NONE;
    1371                 :            : }
    1372                 :            : 
    1373                 :            : 
    1374                 :            : static PyObject*
    1375                 :          6 : pyepoll_get_closed(pyEpoll_Object *self, void *Py_UNUSED(ignored))
    1376                 :            : {
    1377         [ +  + ]:          6 :     if (self->epfd < 0)
    1378                 :          3 :         Py_RETURN_TRUE;
    1379                 :            :     else
    1380                 :          3 :         Py_RETURN_FALSE;
    1381                 :            : }
    1382                 :            : 
    1383                 :            : /*[clinic input]
    1384                 :            : select.epoll.fileno
    1385                 :            : 
    1386                 :            : Return the epoll control file descriptor.
    1387                 :            : [clinic start generated code]*/
    1388                 :            : 
    1389                 :            : static PyObject *
    1390                 :         11 : select_epoll_fileno_impl(pyEpoll_Object *self)
    1391                 :            : /*[clinic end generated code: output=e171375fdc619ba3 input=c11091a6aee60b5c]*/
    1392                 :            : {
    1393         [ +  + ]:         11 :     if (self->epfd < 0)
    1394                 :          3 :         return pyepoll_err_closed();
    1395                 :          8 :     return PyLong_FromLong(self->epfd);
    1396                 :            : }
    1397                 :            : 
    1398                 :            : 
    1399                 :            : /*[clinic input]
    1400                 :            : @classmethod
    1401                 :            : select.epoll.fromfd
    1402                 :            : 
    1403                 :            :     fd: int
    1404                 :            :     /
    1405                 :            : 
    1406                 :            : Create an epoll object from a given control fd.
    1407                 :            : [clinic start generated code]*/
    1408                 :            : 
    1409                 :            : static PyObject *
    1410                 :          1 : select_epoll_fromfd_impl(PyTypeObject *type, int fd)
    1411                 :            : /*[clinic end generated code: output=c15de2a083524e8e input=faecefdb55e3046e]*/
    1412                 :            : {
    1413                 :          1 :     SOCKET s_fd = (SOCKET)fd;
    1414                 :          1 :     return newPyEpoll_Object(type, FD_SETSIZE - 1, s_fd);
    1415                 :            : }
    1416                 :            : 
    1417                 :            : 
    1418                 :            : static PyObject *
    1419                 :      70241 : pyepoll_internal_ctl(int epfd, int op, int fd, unsigned int events)
    1420                 :            : {
    1421                 :            :     struct epoll_event ev;
    1422                 :            :     int result;
    1423                 :            : 
    1424         [ +  + ]:      70241 :     if (epfd < 0)
    1425                 :          3 :         return pyepoll_err_closed();
    1426                 :            : 
    1427      [ +  +  - ]:      70238 :     switch (op) {
    1428                 :      67959 :     case EPOLL_CTL_ADD:
    1429                 :            :     case EPOLL_CTL_MOD:
    1430                 :      67959 :         ev.events = events;
    1431                 :      67959 :         ev.data.fd = fd;
    1432                 :      67959 :         Py_BEGIN_ALLOW_THREADS
    1433                 :      67959 :         result = epoll_ctl(epfd, op, fd, &ev);
    1434                 :      67959 :         Py_END_ALLOW_THREADS
    1435                 :      67959 :         break;
    1436                 :       2279 :     case EPOLL_CTL_DEL:
    1437                 :            :         /* In kernel versions before 2.6.9, the EPOLL_CTL_DEL
    1438                 :            :          * operation required a non-NULL pointer in event, even
    1439                 :            :          * though this argument is ignored. */
    1440                 :       2279 :         Py_BEGIN_ALLOW_THREADS
    1441                 :       2279 :         result = epoll_ctl(epfd, op, fd, &ev);
    1442                 :       2279 :         Py_END_ALLOW_THREADS
    1443                 :       2279 :         break;
    1444                 :          0 :     default:
    1445                 :          0 :         result = -1;
    1446                 :          0 :         errno = EINVAL;
    1447                 :            :     }
    1448                 :            : 
    1449         [ +  + ]:      70238 :     if (result < 0) {
    1450                 :         16 :         PyErr_SetFromErrno(PyExc_OSError);
    1451                 :         16 :         return NULL;
    1452                 :            :     }
    1453                 :      70222 :     Py_RETURN_NONE;
    1454                 :            : }
    1455                 :            : 
    1456                 :            : /*[clinic input]
    1457                 :            : select.epoll.register
    1458                 :            : 
    1459                 :            :     fd: fildes
    1460                 :            :       the target file descriptor of the operation
    1461                 :            :     eventmask: unsigned_int(c_default="EPOLLIN | EPOLLPRI | EPOLLOUT", bitwise=True) = select.EPOLLIN | select.EPOLLPRI | select.EPOLLOUT
    1462                 :            :       a bit set composed of the various EPOLL constants
    1463                 :            : 
    1464                 :            : Registers a new fd or raises an OSError if the fd is already registered.
    1465                 :            : 
    1466                 :            : The epoll interface supports all file descriptors that support poll.
    1467                 :            : [clinic start generated code]*/
    1468                 :            : 
    1469                 :            : static PyObject *
    1470                 :      67931 : select_epoll_register_impl(pyEpoll_Object *self, int fd,
    1471                 :            :                            unsigned int eventmask)
    1472                 :            : /*[clinic end generated code: output=318e5e6386520599 input=a5071b71edfe3578]*/
    1473                 :            : {
    1474                 :      67931 :     return pyepoll_internal_ctl(self->epfd, EPOLL_CTL_ADD, fd, eventmask);
    1475                 :            : }
    1476                 :            : 
    1477                 :            : /*[clinic input]
    1478                 :            : select.epoll.modify
    1479                 :            : 
    1480                 :            :     fd: fildes
    1481                 :            :       the target file descriptor of the operation
    1482                 :            :     eventmask: unsigned_int(bitwise=True)
    1483                 :            :       a bit set composed of the various EPOLL constants
    1484                 :            : 
    1485                 :            : Modify event mask for a registered file descriptor.
    1486                 :            : [clinic start generated code]*/
    1487                 :            : 
    1488                 :            : static PyObject *
    1489                 :         30 : select_epoll_modify_impl(pyEpoll_Object *self, int fd,
    1490                 :            :                          unsigned int eventmask)
    1491                 :            : /*[clinic end generated code: output=7e3447307cff6f65 input=88a83dac53a8c3da]*/
    1492                 :            : {
    1493                 :         30 :     return pyepoll_internal_ctl(self->epfd, EPOLL_CTL_MOD, fd, eventmask);
    1494                 :            : }
    1495                 :            : 
    1496                 :            : /*[clinic input]
    1497                 :            : select.epoll.unregister
    1498                 :            : 
    1499                 :            :     fd: fildes
    1500                 :            :       the target file descriptor of the operation
    1501                 :            : 
    1502                 :            : Remove a registered file descriptor from the epoll object.
    1503                 :            : [clinic start generated code]*/
    1504                 :            : 
    1505                 :            : static PyObject *
    1506                 :       2280 : select_epoll_unregister_impl(pyEpoll_Object *self, int fd)
    1507                 :            : /*[clinic end generated code: output=07c5dbd612a512d4 input=3093f68d3644743d]*/
    1508                 :            : {
    1509                 :       2280 :     return pyepoll_internal_ctl(self->epfd, EPOLL_CTL_DEL, fd, 0);
    1510                 :            : }
    1511                 :            : 
    1512                 :            : /*[clinic input]
    1513                 :            : select.epoll.poll
    1514                 :            : 
    1515                 :            :     timeout as timeout_obj: object = None
    1516                 :            :       the maximum time to wait in seconds (as float);
    1517                 :            :       a timeout of None or -1 makes poll wait indefinitely
    1518                 :            :     maxevents: int = -1
    1519                 :            :       the maximum number of events returned; -1 means no limit
    1520                 :            : 
    1521                 :            : Wait for events on the epoll file descriptor.
    1522                 :            : 
    1523                 :            : Returns a list containing any descriptors that have events to report,
    1524                 :            : as a list of (fd, events) 2-tuples.
    1525                 :            : [clinic start generated code]*/
    1526                 :            : 
    1527                 :            : static PyObject *
    1528                 :      16002 : select_epoll_poll_impl(pyEpoll_Object *self, PyObject *timeout_obj,
    1529                 :            :                        int maxevents)
    1530                 :            : /*[clinic end generated code: output=e02d121a20246c6c input=33d34a5ea430fd5b]*/
    1531                 :            : {
    1532                 :            :     int nfds, i;
    1533                 :      16002 :     PyObject *elist = NULL, *etuple = NULL;
    1534                 :      16002 :     struct epoll_event *evs = NULL;
    1535                 :      16002 :     _PyTime_t timeout = -1, ms = -1, deadline = 0;
    1536                 :            : 
    1537         [ +  + ]:      16002 :     if (self->epfd < 0)
    1538                 :          1 :         return pyepoll_err_closed();
    1539                 :            : 
    1540         [ +  - ]:      16001 :     if (timeout_obj != Py_None) {
    1541                 :            :         /* epoll_wait() has a resolution of 1 millisecond, round towards
    1542                 :            :            infinity to wait at least timeout seconds. */
    1543         [ -  + ]:      16001 :         if (_PyTime_FromSecondsObject(&timeout, timeout_obj,
    1544                 :            :                                       _PyTime_ROUND_TIMEOUT) < 0) {
    1545         [ #  # ]:          0 :             if (PyErr_ExceptionMatches(PyExc_TypeError)) {
    1546                 :          0 :                 PyErr_SetString(PyExc_TypeError,
    1547                 :            :                                 "timeout must be an integer or None");
    1548                 :            :             }
    1549                 :          0 :             return NULL;
    1550                 :            :         }
    1551                 :            : 
    1552                 :      16001 :         ms = _PyTime_AsMilliseconds(timeout, _PyTime_ROUND_CEILING);
    1553   [ +  -  -  + ]:      16001 :         if (ms < INT_MIN || ms > INT_MAX) {
    1554                 :          0 :             PyErr_SetString(PyExc_OverflowError, "timeout is too large");
    1555                 :          0 :             return NULL;
    1556                 :            :         }
    1557                 :            :         /* epoll_wait(2) treats all arbitrary negative numbers the same
    1558                 :            :            for the timeout argument, but -1 is the documented way to block
    1559                 :            :            indefinitely in the epoll_wait(2) documentation, so we set ms
    1560                 :            :            to -1 if the value of ms is a negative number.
    1561                 :            : 
    1562                 :            :            Note that we didn't use INFTIM here since it's non-standard and
    1563                 :            :            isn't available under Linux. */
    1564         [ +  + ]:      16001 :         if (ms < 0) {
    1565                 :       2234 :             ms = -1;
    1566                 :            :         }
    1567                 :            : 
    1568         [ +  + ]:      16001 :         if (timeout >= 0) {
    1569                 :      13767 :             deadline = _PyDeadline_Init(timeout);
    1570                 :            :         }
    1571                 :            :     }
    1572                 :            : 
    1573         [ +  + ]:      16001 :     if (maxevents == -1) {
    1574                 :          1 :         maxevents = FD_SETSIZE-1;
    1575                 :            :     }
    1576         [ -  + ]:      16000 :     else if (maxevents < 1) {
    1577                 :          0 :         PyErr_Format(PyExc_ValueError,
    1578                 :            :                      "maxevents must be greater than 0, got %d",
    1579                 :            :                      maxevents);
    1580                 :          0 :         return NULL;
    1581                 :            :     }
    1582                 :            : 
    1583         [ +  - ]:      16001 :     evs = PyMem_New(struct epoll_event, maxevents);
    1584         [ -  + ]:      16001 :     if (evs == NULL) {
    1585                 :            :         PyErr_NoMemory();
    1586                 :          0 :         return NULL;
    1587                 :            :     }
    1588                 :            : 
    1589                 :            :     do {
    1590                 :      16444 :         Py_BEGIN_ALLOW_THREADS
    1591                 :      16444 :         errno = 0;
    1592                 :      16444 :         nfds = epoll_wait(self->epfd, evs, maxevents, (int)ms);
    1593                 :      16444 :         Py_END_ALLOW_THREADS
    1594                 :            : 
    1595         [ +  + ]:      16444 :         if (errno != EINTR)
    1596                 :      15999 :             break;
    1597                 :            : 
    1598                 :            :         /* poll() was interrupted by a signal */
    1599         [ +  + ]:        445 :         if (PyErr_CheckSignals())
    1600                 :          2 :             goto error;
    1601                 :            : 
    1602         [ +  + ]:        443 :         if (timeout >= 0) {
    1603                 :         14 :             timeout = _PyDeadline_Get(deadline);
    1604         [ -  + ]:         14 :             if (timeout < 0) {
    1605                 :          0 :                 nfds = 0;
    1606                 :          0 :                 break;
    1607                 :            :             }
    1608                 :         14 :             ms = _PyTime_AsMilliseconds(timeout, _PyTime_ROUND_CEILING);
    1609                 :            :             /* retry epoll_wait() with the recomputed timeout */
    1610                 :            :         }
    1611                 :            :     } while(1);
    1612                 :            : 
    1613         [ +  + ]:      15999 :     if (nfds < 0) {
    1614                 :          1 :         PyErr_SetFromErrno(PyExc_OSError);
    1615                 :          1 :         goto error;
    1616                 :            :     }
    1617                 :            : 
    1618                 :      15998 :     elist = PyList_New(nfds);
    1619         [ -  + ]:      15998 :     if (elist == NULL) {
    1620                 :          0 :         goto error;
    1621                 :            :     }
    1622                 :            : 
    1623         [ +  + ]:      53949 :     for (i = 0; i < nfds; i++) {
    1624                 :      37951 :         etuple = Py_BuildValue("iI", evs[i].data.fd, evs[i].events);
    1625         [ -  + ]:      37951 :         if (etuple == NULL) {
    1626         [ #  # ]:          0 :             Py_CLEAR(elist);
    1627                 :          0 :             goto error;
    1628                 :            :         }
    1629                 :      37951 :         PyList_SET_ITEM(elist, i, etuple);
    1630                 :            :     }
    1631                 :            : 
    1632                 :      15998 :     error:
    1633                 :      16001 :     PyMem_Free(evs);
    1634                 :      16001 :     return elist;
    1635                 :            : }
    1636                 :            : 
    1637                 :            : 
    1638                 :            : /*[clinic input]
    1639                 :            : select.epoll.__enter__
    1640                 :            : 
    1641                 :            : [clinic start generated code]*/
    1642                 :            : 
    1643                 :            : static PyObject *
    1644                 :          2 : select_epoll___enter___impl(pyEpoll_Object *self)
    1645                 :            : /*[clinic end generated code: output=ab45d433504db2a0 input=3c22568587efeadb]*/
    1646                 :            : {
    1647         [ -  + ]:          2 :     if (self->epfd < 0)
    1648                 :          0 :         return pyepoll_err_closed();
    1649                 :            : 
    1650                 :          2 :     Py_INCREF(self);
    1651                 :          2 :     return (PyObject *)self;
    1652                 :            : }
    1653                 :            : 
    1654                 :            : /*[clinic input]
    1655                 :            : select.epoll.__exit__
    1656                 :            : 
    1657                 :            :     exc_type:  object = None
    1658                 :            :     exc_value: object = None
    1659                 :            :     exc_tb:    object = None
    1660                 :            :     /
    1661                 :            : 
    1662                 :            : [clinic start generated code]*/
    1663                 :            : 
    1664                 :            : static PyObject *
    1665                 :          2 : select_epoll___exit___impl(pyEpoll_Object *self, PyObject *exc_type,
    1666                 :            :                            PyObject *exc_value, PyObject *exc_tb)
    1667                 :            : /*[clinic end generated code: output=c480f38ce361748e input=7ae81a5a4c1a98d8]*/
    1668                 :            : {
    1669                 :          2 :     _selectstate *state = _selectstate_by_type(Py_TYPE(self));
    1670                 :          2 :     return PyObject_CallMethodObjArgs((PyObject *)self, state->close, NULL);
    1671                 :            : }
    1672                 :            : 
    1673                 :            : static PyGetSetDef pyepoll_getsetlist[] = {
    1674                 :            :     {"closed", (getter)pyepoll_get_closed, NULL,
    1675                 :            :      "True if the epoll handler is closed"},
    1676                 :            :     {0},
    1677                 :            : };
    1678                 :            : 
    1679                 :            : PyDoc_STRVAR(pyepoll_doc,
    1680                 :            : "select.epoll(sizehint=-1, flags=0)\n\
    1681                 :            : \n\
    1682                 :            : Returns an epolling object\n\
    1683                 :            : \n\
    1684                 :            : sizehint must be a positive integer or -1 for the default size. The\n\
    1685                 :            : sizehint is used to optimize internal data structures. It doesn't limit\n\
    1686                 :            : the maximum number of monitored events.");
    1687                 :            : 
    1688                 :            : #endif /* HAVE_EPOLL */
    1689                 :            : 
    1690                 :            : #ifdef HAVE_KQUEUE
    1691                 :            : /* **************************************************************************
    1692                 :            :  *                      kqueue interface for BSD
    1693                 :            :  *
    1694                 :            :  * Copyright (c) 2000 Doug White, 2006 James Knight, 2007 Christian Heimes
    1695                 :            :  * All rights reserved.
    1696                 :            :  *
    1697                 :            :  * Redistribution and use in source and binary forms, with or without
    1698                 :            :  * modification, are permitted provided that the following conditions
    1699                 :            :  * are met:
    1700                 :            :  * 1. Redistributions of source code must retain the above copyright
    1701                 :            :  *    notice, this list of conditions and the following disclaimer.
    1702                 :            :  * 2. Redistributions in binary form must reproduce the above copyright
    1703                 :            :  *    notice, this list of conditions and the following disclaimer in the
    1704                 :            :  *    documentation and/or other materials provided with the distribution.
    1705                 :            :  *
    1706                 :            :  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
    1707                 :            :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    1708                 :            :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    1709                 :            :  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
    1710                 :            :  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    1711                 :            :  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
    1712                 :            :  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    1713                 :            :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    1714                 :            :  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    1715                 :            :  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    1716                 :            :  * SUCH DAMAGE.
    1717                 :            :  */
    1718                 :            : 
    1719                 :            : #ifdef HAVE_SYS_EVENT_H
    1720                 :            : #include <sys/event.h>
    1721                 :            : #endif
    1722                 :            : 
    1723                 :            : PyDoc_STRVAR(kqueue_event_doc,
    1724                 :            : "kevent(ident, filter=KQ_FILTER_READ, flags=KQ_EV_ADD, fflags=0, data=0, udata=0)\n\
    1725                 :            : \n\
    1726                 :            : This object is the equivalent of the struct kevent for the C API.\n\
    1727                 :            : \n\
    1728                 :            : See the kqueue manpage for more detailed information about the meaning\n\
    1729                 :            : of the arguments.\n\
    1730                 :            : \n\
    1731                 :            : One minor note: while you might hope that udata could store a\n\
    1732                 :            : reference to a python object, it cannot, because it is impossible to\n\
    1733                 :            : keep a proper reference count of the object once it's passed into the\n\
    1734                 :            : kernel. Therefore, I have restricted it to only storing an integer.  I\n\
    1735                 :            : recommend ignoring it and simply using the 'ident' field to key off\n\
    1736                 :            : of. You could also set up a dictionary on the python side to store a\n\
    1737                 :            : udata->object mapping.");
    1738                 :            : 
    1739                 :            : typedef struct {
    1740                 :            :     PyObject_HEAD
    1741                 :            :     struct kevent e;
    1742                 :            : } kqueue_event_Object;
    1743                 :            : 
    1744                 :            : #define kqueue_event_Check(op, state) (PyObject_TypeCheck((op), state->kqueue_event_Type))
    1745                 :            : 
    1746                 :            : typedef struct {
    1747                 :            :     PyObject_HEAD
    1748                 :            :     SOCKET kqfd;                /* kqueue control fd */
    1749                 :            : } kqueue_queue_Object;
    1750                 :            : 
    1751                 :            : #if (SIZEOF_UINTPTR_T != SIZEOF_VOID_P)
    1752                 :            : #   error uintptr_t does not match void *!
    1753                 :            : #elif (SIZEOF_UINTPTR_T == SIZEOF_LONG_LONG)
    1754                 :            : #   define T_UINTPTRT         T_ULONGLONG
    1755                 :            : #   define T_INTPTRT          T_LONGLONG
    1756                 :            : #   define UINTPTRT_FMT_UNIT  "K"
    1757                 :            : #   define INTPTRT_FMT_UNIT   "L"
    1758                 :            : #elif (SIZEOF_UINTPTR_T == SIZEOF_LONG)
    1759                 :            : #   define T_UINTPTRT         T_ULONG
    1760                 :            : #   define T_INTPTRT          T_LONG
    1761                 :            : #   define UINTPTRT_FMT_UNIT  "k"
    1762                 :            : #   define INTPTRT_FMT_UNIT   "l"
    1763                 :            : #elif (SIZEOF_UINTPTR_T == SIZEOF_INT)
    1764                 :            : #   define T_UINTPTRT         T_UINT
    1765                 :            : #   define T_INTPTRT          T_INT
    1766                 :            : #   define UINTPTRT_FMT_UNIT  "I"
    1767                 :            : #   define INTPTRT_FMT_UNIT   "i"
    1768                 :            : #else
    1769                 :            : #   error uintptr_t does not match int, long, or long long!
    1770                 :            : #endif
    1771                 :            : 
    1772                 :            : #if SIZEOF_LONG_LONG == 8
    1773                 :            : #   define T_INT64          T_LONGLONG
    1774                 :            : #   define INT64_FMT_UNIT   "L"
    1775                 :            : #elif SIZEOF_LONG == 8
    1776                 :            : #   define T_INT64          T_LONG
    1777                 :            : #   define INT64_FMT_UNIT   "l"
    1778                 :            : #elif SIZEOF_INT == 8
    1779                 :            : #   define T_INT64          T_INT
    1780                 :            : #   define INT64_FMT_UNIT   "i"
    1781                 :            : #else
    1782                 :            : #   define INT64_FMT_UNIT   "_"
    1783                 :            : #endif
    1784                 :            : 
    1785                 :            : #if SIZEOF_LONG_LONG == 4
    1786                 :            : #   define T_UINT32         T_ULONGLONG
    1787                 :            : #   define UINT32_FMT_UNIT  "K"
    1788                 :            : #elif SIZEOF_LONG == 4
    1789                 :            : #   define T_UINT32         T_ULONG
    1790                 :            : #   define UINT32_FMT_UNIT  "k"
    1791                 :            : #elif SIZEOF_INT == 4
    1792                 :            : #   define T_UINT32         T_UINT
    1793                 :            : #   define UINT32_FMT_UNIT  "I"
    1794                 :            : #else
    1795                 :            : #   define UINT32_FMT_UNIT  "_"
    1796                 :            : #endif
    1797                 :            : 
    1798                 :            : /*
    1799                 :            :  * kevent is not standard and its members vary across BSDs.
    1800                 :            :  */
    1801                 :            : #ifdef __NetBSD__
    1802                 :            : #   define FILTER_TYPE      T_UINT32
    1803                 :            : #   define FILTER_FMT_UNIT  UINT32_FMT_UNIT
    1804                 :            : #   define FLAGS_TYPE       T_UINT32
    1805                 :            : #   define FLAGS_FMT_UNIT   UINT32_FMT_UNIT
    1806                 :            : #   define FFLAGS_TYPE      T_UINT32
    1807                 :            : #   define FFLAGS_FMT_UNIT  UINT32_FMT_UNIT
    1808                 :            : #else
    1809                 :            : #   define FILTER_TYPE      T_SHORT
    1810                 :            : #   define FILTER_FMT_UNIT  "h"
    1811                 :            : #   define FLAGS_TYPE       T_USHORT
    1812                 :            : #   define FLAGS_FMT_UNIT   "H"
    1813                 :            : #   define FFLAGS_TYPE      T_UINT
    1814                 :            : #   define FFLAGS_FMT_UNIT  "I"
    1815                 :            : #endif
    1816                 :            : 
    1817                 :            : #if defined(__NetBSD__) || defined(__OpenBSD__)
    1818                 :            : #   define DATA_TYPE        T_INT64
    1819                 :            : #   define DATA_FMT_UNIT    INT64_FMT_UNIT
    1820                 :            : #else
    1821                 :            : #   define DATA_TYPE        T_INTPTRT
    1822                 :            : #   define DATA_FMT_UNIT    INTPTRT_FMT_UNIT
    1823                 :            : #endif
    1824                 :            : 
    1825                 :            : /* Unfortunately, we can't store python objects in udata, because
    1826                 :            :  * kevents in the kernel can be removed without warning, which would
    1827                 :            :  * forever lose the refcount on the object stored with it.
    1828                 :            :  */
    1829                 :            : 
    1830                 :            : #define KQ_OFF(x) offsetof(kqueue_event_Object, x)
    1831                 :            : static struct PyMemberDef kqueue_event_members[] = {
    1832                 :            :     {"ident",           T_UINTPTRT,     KQ_OFF(e.ident)},
    1833                 :            :     {"filter",          FILTER_TYPE,    KQ_OFF(e.filter)},
    1834                 :            :     {"flags",           FLAGS_TYPE,     KQ_OFF(e.flags)},
    1835                 :            :     {"fflags",          T_UINT,         KQ_OFF(e.fflags)},
    1836                 :            :     {"data",            DATA_TYPE,      KQ_OFF(e.data)},
    1837                 :            :     {"udata",           T_UINTPTRT,     KQ_OFF(e.udata)},
    1838                 :            :     {NULL} /* Sentinel */
    1839                 :            : };
    1840                 :            : #undef KQ_OFF
    1841                 :            : 
    1842                 :            : static PyObject *
    1843                 :            : 
    1844                 :            : kqueue_event_repr(kqueue_event_Object *s)
    1845                 :            : {
    1846                 :            :     char buf[1024];
    1847                 :            :     PyOS_snprintf(
    1848                 :            :         buf, sizeof(buf),
    1849                 :            :         "<select.kevent ident=%zu filter=%d flags=0x%x fflags=0x%x "
    1850                 :            :         "data=0x%llx udata=%p>",
    1851                 :            :         (size_t)(s->e.ident), (int)s->e.filter, (unsigned int)s->e.flags,
    1852                 :            :         (unsigned int)s->e.fflags, (long long)(s->e.data), (void *)s->e.udata);
    1853                 :            :     return PyUnicode_FromString(buf);
    1854                 :            : }
    1855                 :            : 
    1856                 :            : static int
    1857                 :            : kqueue_event_init(kqueue_event_Object *self, PyObject *args, PyObject *kwds)
    1858                 :            : {
    1859                 :            :     PyObject *pfd;
    1860                 :            :     static char *kwlist[] = {"ident", "filter", "flags", "fflags",
    1861                 :            :                              "data", "udata", NULL};
    1862                 :            :     static const char fmt[] = "O|"
    1863                 :            :                 FILTER_FMT_UNIT FLAGS_FMT_UNIT FFLAGS_FMT_UNIT DATA_FMT_UNIT
    1864                 :            :                 UINTPTRT_FMT_UNIT ":kevent";
    1865                 :            : 
    1866                 :            :     EV_SET(&(self->e), 0, EVFILT_READ, EV_ADD, 0, 0, 0); /* defaults */
    1867                 :            : 
    1868                 :            :     if (!PyArg_ParseTupleAndKeywords(args, kwds, fmt, kwlist,
    1869                 :            :         &pfd, &(self->e.filter), &(self->e.flags),
    1870                 :            :         &(self->e.fflags), &(self->e.data), &(self->e.udata))) {
    1871                 :            :         return -1;
    1872                 :            :     }
    1873                 :            : 
    1874                 :            :     if (PyLong_Check(pfd)) {
    1875                 :            :         self->e.ident = PyLong_AsSize_t(pfd);
    1876                 :            :     }
    1877                 :            :     else {
    1878                 :            :         self->e.ident = PyObject_AsFileDescriptor(pfd);
    1879                 :            :     }
    1880                 :            :     if (PyErr_Occurred()) {
    1881                 :            :         return -1;
    1882                 :            :     }
    1883                 :            :     return 0;
    1884                 :            : }
    1885                 :            : 
    1886                 :            : static PyObject *
    1887                 :            : kqueue_event_richcompare(kqueue_event_Object *s, kqueue_event_Object *o,
    1888                 :            :                          int op)
    1889                 :            : {
    1890                 :            :     int result;
    1891                 :            :     _selectstate *state = _selectstate_by_type(Py_TYPE(s));
    1892                 :            : 
    1893                 :            :     if (!kqueue_event_Check(o, state)) {
    1894                 :            :         Py_RETURN_NOTIMPLEMENTED;
    1895                 :            :     }
    1896                 :            : 
    1897                 :            : #define CMP(a, b) ((a) != (b)) ? ((a) < (b) ? -1 : 1)
    1898                 :            :     result = CMP(s->e.ident, o->e.ident)
    1899                 :            :            : CMP(s->e.filter, o->e.filter)
    1900                 :            :            : CMP(s->e.flags, o->e.flags)
    1901                 :            :            : CMP(s->e.fflags, o->e.fflags)
    1902                 :            :            : CMP(s->e.data, o->e.data)
    1903                 :            :            : CMP((intptr_t)s->e.udata, (intptr_t)o->e.udata)
    1904                 :            :            : 0;
    1905                 :            : #undef CMP
    1906                 :            : 
    1907                 :            :     Py_RETURN_RICHCOMPARE(result, 0, op);
    1908                 :            : }
    1909                 :            : 
    1910                 :            : static PyType_Slot kqueue_event_Type_slots[] = {
    1911                 :            :     {Py_tp_doc, (void*)kqueue_event_doc},
    1912                 :            :     {Py_tp_init, kqueue_event_init},
    1913                 :            :     {Py_tp_members, kqueue_event_members},
    1914                 :            :     {Py_tp_new, PyType_GenericNew},
    1915                 :            :     {Py_tp_repr, kqueue_event_repr},
    1916                 :            :     {Py_tp_richcompare, kqueue_event_richcompare},
    1917                 :            :     {0, 0},
    1918                 :            : };
    1919                 :            : 
    1920                 :            : static PyType_Spec kqueue_event_Type_spec = {
    1921                 :            :     "select.kevent",
    1922                 :            :     sizeof(kqueue_event_Object),
    1923                 :            :     0,
    1924                 :            :     Py_TPFLAGS_DEFAULT,
    1925                 :            :     kqueue_event_Type_slots
    1926                 :            : };
    1927                 :            : 
    1928                 :            : static PyObject *
    1929                 :            : kqueue_queue_err_closed(void)
    1930                 :            : {
    1931                 :            :     PyErr_SetString(PyExc_ValueError, "I/O operation on closed kqueue object");
    1932                 :            :     return NULL;
    1933                 :            : }
    1934                 :            : 
    1935                 :            : static int
    1936                 :            : kqueue_queue_internal_close(kqueue_queue_Object *self)
    1937                 :            : {
    1938                 :            :     int save_errno = 0;
    1939                 :            :     if (self->kqfd >= 0) {
    1940                 :            :         int kqfd = self->kqfd;
    1941                 :            :         self->kqfd = -1;
    1942                 :            :         Py_BEGIN_ALLOW_THREADS
    1943                 :            :         if (close(kqfd) < 0)
    1944                 :            :             save_errno = errno;
    1945                 :            :         Py_END_ALLOW_THREADS
    1946                 :            :     }
    1947                 :            :     return save_errno;
    1948                 :            : }
    1949                 :            : 
    1950                 :            : static PyObject *
    1951                 :            : newKqueue_Object(PyTypeObject *type, SOCKET fd)
    1952                 :            : {
    1953                 :            :     kqueue_queue_Object *self;
    1954                 :            :     assert(type != NULL);
    1955                 :            :     allocfunc queue_alloc = PyType_GetSlot(type, Py_tp_alloc);
    1956                 :            :     assert(queue_alloc != NULL);
    1957                 :            :     self = (kqueue_queue_Object *) queue_alloc(type, 0);
    1958                 :            :     if (self == NULL) {
    1959                 :            :         return NULL;
    1960                 :            :     }
    1961                 :            : 
    1962                 :            :     if (fd == -1) {
    1963                 :            :         Py_BEGIN_ALLOW_THREADS
    1964                 :            :         self->kqfd = kqueue();
    1965                 :            :         Py_END_ALLOW_THREADS
    1966                 :            :     }
    1967                 :            :     else {
    1968                 :            :         self->kqfd = fd;
    1969                 :            :     }
    1970                 :            :     if (self->kqfd < 0) {
    1971                 :            :         Py_DECREF(self);
    1972                 :            :         PyErr_SetFromErrno(PyExc_OSError);
    1973                 :            :         return NULL;
    1974                 :            :     }
    1975                 :            : 
    1976                 :            :     if (fd == -1) {
    1977                 :            :         if (_Py_set_inheritable(self->kqfd, 0, NULL) < 0) {
    1978                 :            :             Py_DECREF(self);
    1979                 :            :             return NULL;
    1980                 :            :         }
    1981                 :            :     }
    1982                 :            :     return (PyObject *)self;
    1983                 :            : }
    1984                 :            : 
    1985                 :            : /*[clinic input]
    1986                 :            : @classmethod
    1987                 :            : select.kqueue.__new__
    1988                 :            : 
    1989                 :            : Kqueue syscall wrapper.
    1990                 :            : 
    1991                 :            : For example, to start watching a socket for input:
    1992                 :            : >>> kq = kqueue()
    1993                 :            : >>> sock = socket()
    1994                 :            : >>> sock.connect((host, port))
    1995                 :            : >>> kq.control([kevent(sock, KQ_FILTER_WRITE, KQ_EV_ADD)], 0)
    1996                 :            : 
    1997                 :            : To wait one second for it to become writeable:
    1998                 :            : >>> kq.control(None, 1, 1000)
    1999                 :            : 
    2000                 :            : To stop listening:
    2001                 :            : >>> kq.control([kevent(sock, KQ_FILTER_WRITE, KQ_EV_DELETE)], 0)
    2002                 :            : [clinic start generated code]*/
    2003                 :            : 
    2004                 :            : static PyObject *
    2005                 :            : select_kqueue_impl(PyTypeObject *type)
    2006                 :            : /*[clinic end generated code: output=e0ff89f154d56236 input=cf625e49218366e8]*/
    2007                 :            : {
    2008                 :            :     return newKqueue_Object(type, -1);
    2009                 :            : }
    2010                 :            : 
    2011                 :            : static void
    2012                 :            : kqueue_queue_dealloc(kqueue_queue_Object *self)
    2013                 :            : {
    2014                 :            :     PyTypeObject* type = Py_TYPE(self);
    2015                 :            :     kqueue_queue_internal_close(self);
    2016                 :            :     freefunc kqueue_free = PyType_GetSlot(type, Py_tp_free);
    2017                 :            :     kqueue_free((PyObject *)self);
    2018                 :            :     Py_DECREF((PyObject *)type);
    2019                 :            : }
    2020                 :            : 
    2021                 :            : /*[clinic input]
    2022                 :            : select.kqueue.close
    2023                 :            : 
    2024                 :            : Close the kqueue control file descriptor.
    2025                 :            : 
    2026                 :            : Further operations on the kqueue object will raise an exception.
    2027                 :            : [clinic start generated code]*/
    2028                 :            : 
    2029                 :            : static PyObject *
    2030                 :            : select_kqueue_close_impl(kqueue_queue_Object *self)
    2031                 :            : /*[clinic end generated code: output=d1c7df0b407a4bc1 input=0b12d95430e0634c]*/
    2032                 :            : {
    2033                 :            :     errno = kqueue_queue_internal_close(self);
    2034                 :            :     if (errno < 0) {
    2035                 :            :         PyErr_SetFromErrno(PyExc_OSError);
    2036                 :            :         return NULL;
    2037                 :            :     }
    2038                 :            :     Py_RETURN_NONE;
    2039                 :            : }
    2040                 :            : 
    2041                 :            : static PyObject*
    2042                 :            : kqueue_queue_get_closed(kqueue_queue_Object *self, void *Py_UNUSED(ignored))
    2043                 :            : {
    2044                 :            :     if (self->kqfd < 0)
    2045                 :            :         Py_RETURN_TRUE;
    2046                 :            :     else
    2047                 :            :         Py_RETURN_FALSE;
    2048                 :            : }
    2049                 :            : 
    2050                 :            : /*[clinic input]
    2051                 :            : select.kqueue.fileno
    2052                 :            : 
    2053                 :            : Return the kqueue control file descriptor.
    2054                 :            : [clinic start generated code]*/
    2055                 :            : 
    2056                 :            : static PyObject *
    2057                 :            : select_kqueue_fileno_impl(kqueue_queue_Object *self)
    2058                 :            : /*[clinic end generated code: output=716f46112a4f6e5c input=41911c539ca2b0ca]*/
    2059                 :            : {
    2060                 :            :     if (self->kqfd < 0)
    2061                 :            :         return kqueue_queue_err_closed();
    2062                 :            :     return PyLong_FromLong(self->kqfd);
    2063                 :            : }
    2064                 :            : 
    2065                 :            : /*[clinic input]
    2066                 :            : @classmethod
    2067                 :            : select.kqueue.fromfd
    2068                 :            : 
    2069                 :            :     fd: int
    2070                 :            :     /
    2071                 :            : 
    2072                 :            : Create a kqueue object from a given control fd.
    2073                 :            : [clinic start generated code]*/
    2074                 :            : 
    2075                 :            : static PyObject *
    2076                 :            : select_kqueue_fromfd_impl(PyTypeObject *type, int fd)
    2077                 :            : /*[clinic end generated code: output=d02c3c7dc538a653 input=f6172a48ca4ecdd0]*/
    2078                 :            : {
    2079                 :            :     SOCKET s_fd = (SOCKET)fd;
    2080                 :            : 
    2081                 :            :     return newKqueue_Object(type, s_fd);
    2082                 :            : }
    2083                 :            : 
    2084                 :            : /*[clinic input]
    2085                 :            : select.kqueue.control
    2086                 :            : 
    2087                 :            :     changelist: object
    2088                 :            :         Must be an iterable of kevent objects describing the changes to be made
    2089                 :            :         to the kernel's watch list or None.
    2090                 :            :     maxevents: int
    2091                 :            :         The maximum number of events that the kernel will return.
    2092                 :            :     timeout as otimeout: object = None
    2093                 :            :         The maximum time to wait in seconds, or else None to wait forever.
    2094                 :            :         This accepts floats for smaller timeouts, too.
    2095                 :            :     /
    2096                 :            : 
    2097                 :            : Calls the kernel kevent function.
    2098                 :            : [clinic start generated code]*/
    2099                 :            : 
    2100                 :            : static PyObject *
    2101                 :            : select_kqueue_control_impl(kqueue_queue_Object *self, PyObject *changelist,
    2102                 :            :                            int maxevents, PyObject *otimeout)
    2103                 :            : /*[clinic end generated code: output=81324ff5130db7ae input=59c4e30811209c47]*/
    2104                 :            : {
    2105                 :            :     int gotevents = 0;
    2106                 :            :     int nchanges = 0;
    2107                 :            :     int i = 0;
    2108                 :            :     PyObject *seq = NULL, *ei = NULL;
    2109                 :            :     PyObject *result = NULL;
    2110                 :            :     struct kevent *evl = NULL;
    2111                 :            :     struct kevent *chl = NULL;
    2112                 :            :     struct timespec timeoutspec;
    2113                 :            :     struct timespec *ptimeoutspec;
    2114                 :            :     _PyTime_t timeout, deadline = 0;
    2115                 :            :     _selectstate *state = _selectstate_by_type(Py_TYPE(self));
    2116                 :            : 
    2117                 :            :     if (self->kqfd < 0)
    2118                 :            :         return kqueue_queue_err_closed();
    2119                 :            : 
    2120                 :            :     if (maxevents < 0) {
    2121                 :            :         PyErr_Format(PyExc_ValueError,
    2122                 :            :             "Length of eventlist must be 0 or positive, got %d",
    2123                 :            :             maxevents);
    2124                 :            :         return NULL;
    2125                 :            :     }
    2126                 :            : 
    2127                 :            :     if (otimeout == Py_None) {
    2128                 :            :         ptimeoutspec = NULL;
    2129                 :            :     }
    2130                 :            :     else {
    2131                 :            :         if (_PyTime_FromSecondsObject(&timeout,
    2132                 :            :                                       otimeout, _PyTime_ROUND_TIMEOUT) < 0) {
    2133                 :            :             PyErr_Format(PyExc_TypeError,
    2134                 :            :                 "timeout argument must be a number "
    2135                 :            :                 "or None, got %.200s",
    2136                 :            :                 _PyType_Name(Py_TYPE(otimeout)));
    2137                 :            :             return NULL;
    2138                 :            :         }
    2139                 :            : 
    2140                 :            :         if (_PyTime_AsTimespec(timeout, &timeoutspec) == -1)
    2141                 :            :             return NULL;
    2142                 :            : 
    2143                 :            :         if (timeoutspec.tv_sec < 0) {
    2144                 :            :             PyErr_SetString(PyExc_ValueError,
    2145                 :            :                             "timeout must be positive or None");
    2146                 :            :             return NULL;
    2147                 :            :         }
    2148                 :            :         ptimeoutspec = &timeoutspec;
    2149                 :            :     }
    2150                 :            : 
    2151                 :            :     if (changelist != Py_None) {
    2152                 :            :         seq = PySequence_Fast(changelist, "changelist is not iterable");
    2153                 :            :         if (seq == NULL) {
    2154                 :            :             return NULL;
    2155                 :            :         }
    2156                 :            :         if (PySequence_Fast_GET_SIZE(seq) > INT_MAX) {
    2157                 :            :             PyErr_SetString(PyExc_OverflowError,
    2158                 :            :                             "changelist is too long");
    2159                 :            :             goto error;
    2160                 :            :         }
    2161                 :            :         nchanges = (int)PySequence_Fast_GET_SIZE(seq);
    2162                 :            : 
    2163                 :            :         chl = PyMem_New(struct kevent, nchanges);
    2164                 :            :         if (chl == NULL) {
    2165                 :            :             PyErr_NoMemory();
    2166                 :            :             goto error;
    2167                 :            :         }
    2168                 :            :         _selectstate *state = _selectstate_by_type(Py_TYPE(self));
    2169                 :            :         for (i = 0; i < nchanges; ++i) {
    2170                 :            :             ei = PySequence_Fast_GET_ITEM(seq, i);
    2171                 :            :             if (!kqueue_event_Check(ei, state)) {
    2172                 :            :                 PyErr_SetString(PyExc_TypeError,
    2173                 :            :                     "changelist must be an iterable of "
    2174                 :            :                     "select.kevent objects");
    2175                 :            :                 goto error;
    2176                 :            :             }
    2177                 :            :             chl[i] = ((kqueue_event_Object *)ei)->e;
    2178                 :            :         }
    2179                 :            :         Py_CLEAR(seq);
    2180                 :            :     }
    2181                 :            : 
    2182                 :            :     /* event list */
    2183                 :            :     if (maxevents) {
    2184                 :            :         evl = PyMem_New(struct kevent, maxevents);
    2185                 :            :         if (evl == NULL) {
    2186                 :            :             PyErr_NoMemory();
    2187                 :            :             goto error;
    2188                 :            :         }
    2189                 :            :     }
    2190                 :            : 
    2191                 :            :     if (ptimeoutspec) {
    2192                 :            :         deadline = _PyDeadline_Init(timeout);
    2193                 :            :     }
    2194                 :            : 
    2195                 :            :     do {
    2196                 :            :         Py_BEGIN_ALLOW_THREADS
    2197                 :            :         errno = 0;
    2198                 :            :         gotevents = kevent(self->kqfd, chl, nchanges,
    2199                 :            :                            evl, maxevents, ptimeoutspec);
    2200                 :            :         Py_END_ALLOW_THREADS
    2201                 :            : 
    2202                 :            :         if (errno != EINTR)
    2203                 :            :             break;
    2204                 :            : 
    2205                 :            :         /* kevent() was interrupted by a signal */
    2206                 :            :         if (PyErr_CheckSignals())
    2207                 :            :             goto error;
    2208                 :            : 
    2209                 :            :         if (ptimeoutspec) {
    2210                 :            :             timeout = _PyDeadline_Get(deadline);
    2211                 :            :             if (timeout < 0) {
    2212                 :            :                 gotevents = 0;
    2213                 :            :                 break;
    2214                 :            :             }
    2215                 :            :             if (_PyTime_AsTimespec(timeout, &timeoutspec) == -1)
    2216                 :            :                 goto error;
    2217                 :            :             /* retry kevent() with the recomputed timeout */
    2218                 :            :         }
    2219                 :            :     } while (1);
    2220                 :            : 
    2221                 :            :     if (gotevents == -1) {
    2222                 :            :         PyErr_SetFromErrno(PyExc_OSError);
    2223                 :            :         goto error;
    2224                 :            :     }
    2225                 :            : 
    2226                 :            :     result = PyList_New(gotevents);
    2227                 :            :     if (result == NULL) {
    2228                 :            :         goto error;
    2229                 :            :     }
    2230                 :            : 
    2231                 :            :     for (i = 0; i < gotevents; i++) {
    2232                 :            :         kqueue_event_Object *ch;
    2233                 :            : 
    2234                 :            :         ch = PyObject_New(kqueue_event_Object, state->kqueue_event_Type);
    2235                 :            :         if (ch == NULL) {
    2236                 :            :             goto error;
    2237                 :            :         }
    2238                 :            :         ch->e = evl[i];
    2239                 :            :         PyList_SET_ITEM(result, i, (PyObject *)ch);
    2240                 :            :     }
    2241                 :            :     PyMem_Free(chl);
    2242                 :            :     PyMem_Free(evl);
    2243                 :            :     return result;
    2244                 :            : 
    2245                 :            :     error:
    2246                 :            :     PyMem_Free(chl);
    2247                 :            :     PyMem_Free(evl);
    2248                 :            :     Py_XDECREF(result);
    2249                 :            :     Py_XDECREF(seq);
    2250                 :            :     return NULL;
    2251                 :            : }
    2252                 :            : 
    2253                 :            : static PyGetSetDef kqueue_queue_getsetlist[] = {
    2254                 :            :     {"closed", (getter)kqueue_queue_get_closed, NULL,
    2255                 :            :      "True if the kqueue handler is closed"},
    2256                 :            :     {0},
    2257                 :            : };
    2258                 :            : 
    2259                 :            : #endif /* HAVE_KQUEUE */
    2260                 :            : 
    2261                 :            : 
    2262                 :            : /* ************************************************************************ */
    2263                 :            : 
    2264                 :            : #include "clinic/selectmodule.c.h"
    2265                 :            : 
    2266                 :            : #if defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL)
    2267                 :            : 
    2268                 :            : static PyMethodDef poll_methods[] = {
    2269                 :            :     SELECT_POLL_REGISTER_METHODDEF
    2270                 :            :     SELECT_POLL_MODIFY_METHODDEF
    2271                 :            :     SELECT_POLL_UNREGISTER_METHODDEF
    2272                 :            :     SELECT_POLL_POLL_METHODDEF
    2273                 :            :     {NULL, NULL}           /* sentinel */
    2274                 :            : };
    2275                 :            : 
    2276                 :            : 
    2277                 :            : static PyType_Slot poll_Type_slots[] = {
    2278                 :            :     {Py_tp_dealloc, poll_dealloc},
    2279                 :            :     {Py_tp_methods, poll_methods},
    2280                 :            :     {0, 0},
    2281                 :            : };
    2282                 :            : 
    2283                 :            : static PyType_Spec poll_Type_spec = {
    2284                 :            :     .name = "select.poll",
    2285                 :            :     .basicsize = sizeof(pollObject),
    2286                 :            :     .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION,
    2287                 :            :     .slots = poll_Type_slots,
    2288                 :            : };
    2289                 :            : 
    2290                 :            : #ifdef HAVE_SYS_DEVPOLL_H
    2291                 :            : 
    2292                 :            : static PyMethodDef devpoll_methods[] = {
    2293                 :            :     SELECT_DEVPOLL_REGISTER_METHODDEF
    2294                 :            :     SELECT_DEVPOLL_MODIFY_METHODDEF
    2295                 :            :     SELECT_DEVPOLL_UNREGISTER_METHODDEF
    2296                 :            :     SELECT_DEVPOLL_POLL_METHODDEF
    2297                 :            :     SELECT_DEVPOLL_CLOSE_METHODDEF
    2298                 :            :     SELECT_DEVPOLL_FILENO_METHODDEF
    2299                 :            :     {NULL,              NULL}           /* sentinel */
    2300                 :            : };
    2301                 :            : 
    2302                 :            : #endif  /* HAVE_SYS_DEVPOLL_H */
    2303                 :            : 
    2304                 :            : #endif /* HAVE_POLL */
    2305                 :            : 
    2306                 :            : #ifdef HAVE_EPOLL
    2307                 :            : 
    2308                 :            : static PyMethodDef pyepoll_methods[] = {
    2309                 :            :     SELECT_EPOLL_FROMFD_METHODDEF
    2310                 :            :     SELECT_EPOLL_CLOSE_METHODDEF
    2311                 :            :     SELECT_EPOLL_FILENO_METHODDEF
    2312                 :            :     SELECT_EPOLL_MODIFY_METHODDEF
    2313                 :            :     SELECT_EPOLL_REGISTER_METHODDEF
    2314                 :            :     SELECT_EPOLL_UNREGISTER_METHODDEF
    2315                 :            :     SELECT_EPOLL_POLL_METHODDEF
    2316                 :            :     SELECT_EPOLL___ENTER___METHODDEF
    2317                 :            :     SELECT_EPOLL___EXIT___METHODDEF
    2318                 :            :     {NULL,      NULL},
    2319                 :            : };
    2320                 :            : 
    2321                 :            : static PyType_Slot pyEpoll_Type_slots[] = {
    2322                 :            :     {Py_tp_dealloc, pyepoll_dealloc},
    2323                 :            :     {Py_tp_doc, (void*)pyepoll_doc},
    2324                 :            :     {Py_tp_getattro, PyObject_GenericGetAttr},
    2325                 :            :     {Py_tp_getset, pyepoll_getsetlist},
    2326                 :            :     {Py_tp_methods, pyepoll_methods},
    2327                 :            :     {Py_tp_new, select_epoll},
    2328                 :            :     {0, 0},
    2329                 :            : };
    2330                 :            : 
    2331                 :            : static PyType_Spec pyEpoll_Type_spec = {
    2332                 :            :     "select.epoll",
    2333                 :            :     sizeof(pyEpoll_Object),
    2334                 :            :     0,
    2335                 :            :     Py_TPFLAGS_DEFAULT,
    2336                 :            :     pyEpoll_Type_slots
    2337                 :            : };
    2338                 :            : 
    2339                 :            : #endif /* HAVE_EPOLL */
    2340                 :            : 
    2341                 :            : #ifdef HAVE_KQUEUE
    2342                 :            : 
    2343                 :            : static PyMethodDef kqueue_queue_methods[] = {
    2344                 :            :     SELECT_KQUEUE_FROMFD_METHODDEF
    2345                 :            :     SELECT_KQUEUE_CLOSE_METHODDEF
    2346                 :            :     SELECT_KQUEUE_FILENO_METHODDEF
    2347                 :            :     SELECT_KQUEUE_CONTROL_METHODDEF
    2348                 :            :     {NULL,      NULL},
    2349                 :            : };
    2350                 :            : 
    2351                 :            : static PyType_Slot kqueue_queue_Type_slots[] = {
    2352                 :            :     {Py_tp_dealloc, kqueue_queue_dealloc},
    2353                 :            :     {Py_tp_doc, (void*)select_kqueue__doc__},
    2354                 :            :     {Py_tp_getset, kqueue_queue_getsetlist},
    2355                 :            :     {Py_tp_methods, kqueue_queue_methods},
    2356                 :            :     {Py_tp_new, select_kqueue},
    2357                 :            :     {0, 0},
    2358                 :            : };
    2359                 :            : 
    2360                 :            : static PyType_Spec kqueue_queue_Type_spec = {
    2361                 :            :     "select.kqueue",
    2362                 :            :     sizeof(kqueue_queue_Object),
    2363                 :            :     0,
    2364                 :            :     Py_TPFLAGS_DEFAULT,
    2365                 :            :     kqueue_queue_Type_slots
    2366                 :            : };
    2367                 :            : 
    2368                 :            : #endif /* HAVE_KQUEUE */
    2369                 :            : 
    2370                 :            : 
    2371                 :            : 
    2372                 :            : 
    2373                 :            : 
    2374                 :            : /* ************************************************************************ */
    2375                 :            : 
    2376                 :            : 
    2377                 :            : static PyMethodDef select_methods[] = {
    2378                 :            :     SELECT_SELECT_METHODDEF
    2379                 :            :     SELECT_POLL_METHODDEF
    2380                 :            :     SELECT_DEVPOLL_METHODDEF
    2381                 :            :     {0,         0},     /* sentinel */
    2382                 :            : };
    2383                 :            : 
    2384                 :            : PyDoc_STRVAR(module_doc,
    2385                 :            : "This module supports asynchronous I/O on multiple file descriptors.\n\
    2386                 :            : \n\
    2387                 :            : *** IMPORTANT NOTICE ***\n\
    2388                 :            : On Windows, only sockets are supported; on Unix, all file descriptors.");
    2389                 :            : 
    2390                 :            : 
    2391                 :            : 
    2392                 :            : static int
    2393                 :      37152 : _select_traverse(PyObject *module, visitproc visit, void *arg)
    2394                 :            : {
    2395                 :      37152 :     _selectstate *state = get_select_state(module);
    2396                 :            : 
    2397   [ +  -  -  + ]:      37152 :     Py_VISIT(state->close);
    2398   [ +  -  -  + ]:      37152 :     Py_VISIT(state->poll_Type);
    2399   [ -  +  -  - ]:      37152 :     Py_VISIT(state->devpoll_Type);
    2400   [ +  +  -  + ]:      37152 :     Py_VISIT(state->pyEpoll_Type);
    2401   [ -  +  -  - ]:      37152 :     Py_VISIT(state->kqueue_event_Type);
    2402   [ -  +  -  - ]:      37152 :     Py_VISIT(state->kqueue_queue_Type);
    2403                 :      37152 :     return 0;
    2404                 :            : }
    2405                 :            : 
    2406                 :            : static int
    2407                 :       2424 : _select_clear(PyObject *module)
    2408                 :            : {
    2409                 :       2424 :     _selectstate *state = get_select_state(module);
    2410                 :            : 
    2411         [ +  + ]:       2424 :     Py_CLEAR(state->close);
    2412         [ +  + ]:       2424 :     Py_CLEAR(state->poll_Type);
    2413         [ -  + ]:       2424 :     Py_CLEAR(state->devpoll_Type);
    2414         [ +  + ]:       2424 :     Py_CLEAR(state->pyEpoll_Type);
    2415         [ -  + ]:       2424 :     Py_CLEAR(state->kqueue_event_Type);
    2416         [ -  + ]:       2424 :     Py_CLEAR(state->kqueue_queue_Type);
    2417                 :       2424 :     return 0;
    2418                 :            : }
    2419                 :            : 
    2420                 :            : static void
    2421                 :       1212 : _select_free(void *module)
    2422                 :            : {
    2423                 :       1212 :     _select_clear((PyObject *)module);
    2424                 :       1212 : }
    2425                 :            : 
    2426                 :            : int
    2427                 :       1212 : _select_exec(PyObject *m)
    2428                 :            : {
    2429                 :       1212 :     _selectstate *state = get_select_state(m);
    2430                 :            : 
    2431                 :       1212 :     state->close = PyUnicode_InternFromString("close");
    2432         [ -  + ]:       1212 :     if (state->close == NULL) {
    2433                 :          0 :         return -1;
    2434                 :            :     }
    2435         [ -  + ]:       1212 :     if (PyModule_AddObjectRef(m, "error", PyExc_OSError) < 0) {
    2436                 :          0 :         return -1;
    2437                 :            :     }
    2438                 :            : 
    2439                 :            : #ifdef PIPE_BUF
    2440                 :            : #ifdef HAVE_BROKEN_PIPE_BUF
    2441                 :            : #undef PIPE_BUF
    2442                 :            : #define PIPE_BUF 512
    2443                 :            : #endif
    2444                 :       1212 :     PyModule_AddIntMacro(m, PIPE_BUF);
    2445                 :            : #endif
    2446                 :            : 
    2447                 :            : #if defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL)
    2448                 :            : #ifdef __APPLE__
    2449                 :            :     if (select_have_broken_poll()) {
    2450                 :            :         if (PyObject_DelAttrString(m, "poll") == -1) {
    2451                 :            :             PyErr_Clear();
    2452                 :            :         }
    2453                 :            :     } else {
    2454                 :            : #else
    2455                 :            :     {
    2456                 :            : #endif
    2457                 :       1212 :         state->poll_Type = (PyTypeObject *)PyType_FromModuleAndSpec(
    2458                 :            :             m, &poll_Type_spec, NULL);
    2459         [ -  + ]:       1212 :         if (state->poll_Type == NULL) {
    2460                 :          0 :             return -1;
    2461                 :            :         }
    2462                 :            : 
    2463                 :       1212 :         PyModule_AddIntMacro(m, POLLIN);
    2464                 :       1212 :         PyModule_AddIntMacro(m, POLLPRI);
    2465                 :       1212 :         PyModule_AddIntMacro(m, POLLOUT);
    2466                 :       1212 :         PyModule_AddIntMacro(m, POLLERR);
    2467                 :       1212 :         PyModule_AddIntMacro(m, POLLHUP);
    2468                 :       1212 :         PyModule_AddIntMacro(m, POLLNVAL);
    2469                 :            : 
    2470                 :            : #ifdef POLLRDNORM
    2471                 :       1212 :         PyModule_AddIntMacro(m, POLLRDNORM);
    2472                 :            : #endif
    2473                 :            : #ifdef POLLRDBAND
    2474                 :       1212 :         PyModule_AddIntMacro(m, POLLRDBAND);
    2475                 :            : #endif
    2476                 :            : #ifdef POLLWRNORM
    2477                 :       1212 :         PyModule_AddIntMacro(m, POLLWRNORM);
    2478                 :            : #endif
    2479                 :            : #ifdef POLLWRBAND
    2480                 :       1212 :         PyModule_AddIntMacro(m, POLLWRBAND);
    2481                 :            : #endif
    2482                 :            : #ifdef POLLMSG
    2483                 :       1212 :         PyModule_AddIntMacro(m, POLLMSG);
    2484                 :            : #endif
    2485                 :            : #ifdef POLLRDHUP
    2486                 :            :         /* Kernel 2.6.17+ */
    2487                 :       1212 :         PyModule_AddIntMacro(m, POLLRDHUP);
    2488                 :            : #endif
    2489                 :            :     }
    2490                 :            : #endif /* HAVE_POLL */
    2491                 :            : 
    2492                 :            : #ifdef HAVE_SYS_DEVPOLL_H
    2493                 :            :     state->devpoll_Type = (PyTypeObject *)PyType_FromModuleAndSpec(
    2494                 :            :         m, &devpoll_Type_spec, NULL);
    2495                 :            :     if (state->devpoll_Type == NULL) {
    2496                 :            :         return -1;
    2497                 :            :     }
    2498                 :            : #endif
    2499                 :            : 
    2500                 :            : #ifdef HAVE_EPOLL
    2501                 :       1212 :     state->pyEpoll_Type = (PyTypeObject *)PyType_FromModuleAndSpec(
    2502                 :            :         m, &pyEpoll_Type_spec, NULL);
    2503         [ -  + ]:       1212 :     if (state->pyEpoll_Type == NULL) {
    2504                 :          0 :         return -1;
    2505                 :            :     }
    2506         [ -  + ]:       1212 :     if (PyModule_AddType(m, state->pyEpoll_Type) < 0) {
    2507                 :          0 :         return -1;
    2508                 :            :     }
    2509                 :            : 
    2510                 :       1212 :     PyModule_AddIntMacro(m, EPOLLIN);
    2511                 :       1212 :     PyModule_AddIntMacro(m, EPOLLOUT);
    2512                 :       1212 :     PyModule_AddIntMacro(m, EPOLLPRI);
    2513                 :       1212 :     PyModule_AddIntMacro(m, EPOLLERR);
    2514                 :       1212 :     PyModule_AddIntMacro(m, EPOLLHUP);
    2515                 :            : #ifdef EPOLLRDHUP
    2516                 :            :     /* Kernel 2.6.17 */
    2517                 :       1212 :     PyModule_AddIntMacro(m, EPOLLRDHUP);
    2518                 :            : #endif
    2519                 :       1212 :     PyModule_AddIntMacro(m, EPOLLET);
    2520                 :            : #ifdef EPOLLONESHOT
    2521                 :            :     /* Kernel 2.6.2+ */
    2522                 :       1212 :     PyModule_AddIntMacro(m, EPOLLONESHOT);
    2523                 :            : #endif
    2524                 :            : #ifdef EPOLLEXCLUSIVE
    2525                 :       1212 :     PyModule_AddIntMacro(m, EPOLLEXCLUSIVE);
    2526                 :            : #endif
    2527                 :            : 
    2528                 :            : #ifdef EPOLLRDNORM
    2529                 :       1212 :     PyModule_AddIntMacro(m, EPOLLRDNORM);
    2530                 :            : #endif
    2531                 :            : #ifdef EPOLLRDBAND
    2532                 :       1212 :     PyModule_AddIntMacro(m, EPOLLRDBAND);
    2533                 :            : #endif
    2534                 :            : #ifdef EPOLLWRNORM
    2535                 :       1212 :     PyModule_AddIntMacro(m, EPOLLWRNORM);
    2536                 :            : #endif
    2537                 :            : #ifdef EPOLLWRBAND
    2538                 :       1212 :     PyModule_AddIntMacro(m, EPOLLWRBAND);
    2539                 :            : #endif
    2540                 :            : #ifdef EPOLLMSG
    2541                 :       1212 :     PyModule_AddIntMacro(m, EPOLLMSG);
    2542                 :            : #endif
    2543                 :            : 
    2544                 :            : #ifdef EPOLL_CLOEXEC
    2545                 :       1212 :     PyModule_AddIntMacro(m, EPOLL_CLOEXEC);
    2546                 :            : #endif
    2547                 :            : #endif /* HAVE_EPOLL */
    2548                 :            : 
    2549                 :            : #ifdef HAVE_KQUEUE
    2550                 :            :     state->kqueue_event_Type = (PyTypeObject *)PyType_FromModuleAndSpec(
    2551                 :            :         m, &kqueue_event_Type_spec, NULL);
    2552                 :            :     if (state->kqueue_event_Type == NULL) {
    2553                 :            :         return -1;
    2554                 :            :     }
    2555                 :            :     if (PyModule_AddType(m, state->kqueue_event_Type) < 0) {
    2556                 :            :         return -1;
    2557                 :            :     }
    2558                 :            : 
    2559                 :            :     state->kqueue_queue_Type = (PyTypeObject *)PyType_FromModuleAndSpec(
    2560                 :            :         m, &kqueue_queue_Type_spec, NULL);
    2561                 :            :     if (state->kqueue_queue_Type == NULL) {
    2562                 :            :         return -1;
    2563                 :            :     }
    2564                 :            :     if (PyModule_AddType(m, state->kqueue_queue_Type) < 0) {
    2565                 :            :         return -1;
    2566                 :            :     }
    2567                 :            : 
    2568                 :            :     /* event filters */
    2569                 :            :     PyModule_AddIntConstant(m, "KQ_FILTER_READ", EVFILT_READ);
    2570                 :            :     PyModule_AddIntConstant(m, "KQ_FILTER_WRITE", EVFILT_WRITE);
    2571                 :            : #ifdef EVFILT_AIO
    2572                 :            :     PyModule_AddIntConstant(m, "KQ_FILTER_AIO", EVFILT_AIO);
    2573                 :            : #endif
    2574                 :            : #ifdef EVFILT_VNODE
    2575                 :            :     PyModule_AddIntConstant(m, "KQ_FILTER_VNODE", EVFILT_VNODE);
    2576                 :            : #endif
    2577                 :            : #ifdef EVFILT_PROC
    2578                 :            :     PyModule_AddIntConstant(m, "KQ_FILTER_PROC", EVFILT_PROC);
    2579                 :            : #endif
    2580                 :            : #ifdef EVFILT_NETDEV
    2581                 :            :     PyModule_AddIntConstant(m, "KQ_FILTER_NETDEV", EVFILT_NETDEV);
    2582                 :            : #endif
    2583                 :            : #ifdef EVFILT_SIGNAL
    2584                 :            :     PyModule_AddIntConstant(m, "KQ_FILTER_SIGNAL", EVFILT_SIGNAL);
    2585                 :            : #endif
    2586                 :            :     PyModule_AddIntConstant(m, "KQ_FILTER_TIMER", EVFILT_TIMER);
    2587                 :            : 
    2588                 :            :     /* event flags */
    2589                 :            :     PyModule_AddIntConstant(m, "KQ_EV_ADD", EV_ADD);
    2590                 :            :     PyModule_AddIntConstant(m, "KQ_EV_DELETE", EV_DELETE);
    2591                 :            :     PyModule_AddIntConstant(m, "KQ_EV_ENABLE", EV_ENABLE);
    2592                 :            :     PyModule_AddIntConstant(m, "KQ_EV_DISABLE", EV_DISABLE);
    2593                 :            :     PyModule_AddIntConstant(m, "KQ_EV_ONESHOT", EV_ONESHOT);
    2594                 :            :     PyModule_AddIntConstant(m, "KQ_EV_CLEAR", EV_CLEAR);
    2595                 :            : 
    2596                 :            : #ifdef EV_SYSFLAGS
    2597                 :            :     PyModule_AddIntConstant(m, "KQ_EV_SYSFLAGS", EV_SYSFLAGS);
    2598                 :            : #endif
    2599                 :            : #ifdef EV_FLAG1
    2600                 :            :     PyModule_AddIntConstant(m, "KQ_EV_FLAG1", EV_FLAG1);
    2601                 :            : #endif
    2602                 :            : 
    2603                 :            :     PyModule_AddIntConstant(m, "KQ_EV_EOF", EV_EOF);
    2604                 :            :     PyModule_AddIntConstant(m, "KQ_EV_ERROR", EV_ERROR);
    2605                 :            : 
    2606                 :            :     /* READ WRITE filter flag */
    2607                 :            : #ifdef NOTE_LOWAT
    2608                 :            :     PyModule_AddIntConstant(m, "KQ_NOTE_LOWAT", NOTE_LOWAT);
    2609                 :            : #endif
    2610                 :            : 
    2611                 :            :     /* VNODE filter flags  */
    2612                 :            : #ifdef EVFILT_VNODE
    2613                 :            :     PyModule_AddIntConstant(m, "KQ_NOTE_DELETE", NOTE_DELETE);
    2614                 :            :     PyModule_AddIntConstant(m, "KQ_NOTE_WRITE", NOTE_WRITE);
    2615                 :            :     PyModule_AddIntConstant(m, "KQ_NOTE_EXTEND", NOTE_EXTEND);
    2616                 :            :     PyModule_AddIntConstant(m, "KQ_NOTE_ATTRIB", NOTE_ATTRIB);
    2617                 :            :     PyModule_AddIntConstant(m, "KQ_NOTE_LINK", NOTE_LINK);
    2618                 :            :     PyModule_AddIntConstant(m, "KQ_NOTE_RENAME", NOTE_RENAME);
    2619                 :            :     PyModule_AddIntConstant(m, "KQ_NOTE_REVOKE", NOTE_REVOKE);
    2620                 :            : #endif
    2621                 :            : 
    2622                 :            :     /* PROC filter flags  */
    2623                 :            : #ifdef EVFILT_PROC
    2624                 :            :     PyModule_AddIntConstant(m, "KQ_NOTE_EXIT", NOTE_EXIT);
    2625                 :            :     PyModule_AddIntConstant(m, "KQ_NOTE_FORK", NOTE_FORK);
    2626                 :            :     PyModule_AddIntConstant(m, "KQ_NOTE_EXEC", NOTE_EXEC);
    2627                 :            :     PyModule_AddIntConstant(m, "KQ_NOTE_PCTRLMASK", NOTE_PCTRLMASK);
    2628                 :            :     PyModule_AddIntConstant(m, "KQ_NOTE_PDATAMASK", NOTE_PDATAMASK);
    2629                 :            : 
    2630                 :            :     PyModule_AddIntConstant(m, "KQ_NOTE_TRACK", NOTE_TRACK);
    2631                 :            :     PyModule_AddIntConstant(m, "KQ_NOTE_CHILD", NOTE_CHILD);
    2632                 :            :     PyModule_AddIntConstant(m, "KQ_NOTE_TRACKERR", NOTE_TRACKERR);
    2633                 :            : #endif
    2634                 :            : 
    2635                 :            :     /* NETDEV filter flags */
    2636                 :            : #ifdef EVFILT_NETDEV
    2637                 :            :     PyModule_AddIntConstant(m, "KQ_NOTE_LINKUP", NOTE_LINKUP);
    2638                 :            :     PyModule_AddIntConstant(m, "KQ_NOTE_LINKDOWN", NOTE_LINKDOWN);
    2639                 :            :     PyModule_AddIntConstant(m, "KQ_NOTE_LINKINV", NOTE_LINKINV);
    2640                 :            : #endif
    2641                 :            : 
    2642                 :            : #endif /* HAVE_KQUEUE */
    2643                 :       1212 :     return 0;
    2644                 :            : }
    2645                 :            : 
    2646                 :            : static PyModuleDef_Slot _select_slots[] = {
    2647                 :            :     {Py_mod_exec, _select_exec},
    2648                 :            :     {0, NULL}
    2649                 :            : };
    2650                 :            : 
    2651                 :            : static struct PyModuleDef selectmodule = {
    2652                 :            :     PyModuleDef_HEAD_INIT,
    2653                 :            :     .m_name = "select",
    2654                 :            :     .m_doc = module_doc,
    2655                 :            :     .m_size = sizeof(_selectstate),
    2656                 :            :     .m_methods = select_methods,
    2657                 :            :     .m_slots = _select_slots,
    2658                 :            :     .m_traverse = _select_traverse,
    2659                 :            :     .m_clear = _select_clear,
    2660                 :            :     .m_free = _select_free,
    2661                 :            : };
    2662                 :            : 
    2663                 :            : PyMODINIT_FUNC
    2664                 :       1212 : PyInit_select(void)
    2665                 :            : {
    2666                 :       1212 :     return PyModuleDef_Init(&selectmodule);
    2667                 :            : }

Generated by: LCOV version 1.14