LCOV - code coverage report
Current view: top level - Modules - selectmodule.c (source / functions) Hit Total Coverage
Test: CPython 3.12 LCOV report [commit 5e6661bce9] Lines: 100 505 19.8 %
Date: 2023-03-20 08:15:36 Functions: 11 34 32.4 %
Branches: 32 273 11.7 %

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

Generated by: LCOV version 1.14