/* select - Module containing unix select(2) call. Under Unix, the file descriptors are small integers. Under Win32, select only exists for sockets, and sockets may have any value except INVALID_SOCKET. Under BeOS, we suffer the same dichotomy as Win32; sockets can be anything >= 0.*/ #include "Python.h" #ifdef __APPLE__ /* Perform runtime testing for a broken poll on OSX to make it easier * to use the same binary on multiple releases of the OS. */#undef HAVE_BROKEN_POLL#endif /* Windows #defines FD_SETSIZE to 64 if FD_SETSIZE isn't already defined. 64 is too small (too many people have bumped into that limit). Here we boost it. Users who want even more than the boosted limit should #define FD_SETSIZE higher before this; e.g., via compiler /D switch.*/#if defined(MS_WINDOWS) && !defined(FD_SETSIZE)#define FD_SETSIZE 512#endif #if defined(HAVE_POLL_H)#include <poll.h>#elif defined(HAVE_SYS_POLL_H)#include <sys/poll.h>#endif #ifdef __sgi/* This is missing from unistd.h */extern void bzero(void *, int);#endif #ifdef HAVE_SYS_TYPES_H#include <sys/types.h>#endif #if defined(PYOS_OS2) && !defined(PYCC_GCC)#include <sys/time.h>#include <utils.h>#endif #ifdef MS_WINDOWS# include <winsock.h>#else# define SOCKET int# ifdef __BEOS__# include <net/socket.h># elif defined(__VMS)# include <socket.h># endif#endif static PyObject *SelectError; /* list of Python objects and their file descriptor */typedef struct { PyObject *obj; /* owned reference */ SOCKET fd; int sentinel; /* -1 == sentinel */} pylist; static voidreap_obj(pylist fd2obj[FD_SETSIZE + 1]){ int i; for (i = 0; i < FD_SETSIZE + 1 && fd2obj[i].sentinel >= 0; i++) { Py_XDECREF(fd2obj[i].obj); fd2obj[i].obj = NULL; } fd2obj[0].sentinel = -1;} /* returns -1 and sets the Python exception if an error occurred, otherwise returns a number >= 0*/static intseq2set(PyObject *seq, fd_set *set, pylist fd2obj[FD_SETSIZE + 1]){ int i; int max = -1; int index = 0; int len = -1; PyObject* fast_seq = NULL; PyObject* o = NULL; fd2obj[0].obj = (PyObject*)0; /* set list to zero size */ FD_ZERO(set); fast_seq=PySequence_Fast(seq, "arguments 1-3 must be sequences"); if (!fast_seq) return -1; len = PySequence_Fast_GET_SIZE(fast_seq); for (i = 0; i < len; i++) { SOCKET v; /* any intervening fileno() calls could decr this refcnt */ if (!(o = PySequence_Fast_GET_ITEM(fast_seq, i))) return -1; Py_INCREF(o); v = PyObject_AsFileDescriptor( o ); if (v == -1) goto finally; #if defined(_MSC_VER) max = 0; /* not used for Win32 */#else /* !_MSC_VER */ if (v < 0 || v >= FD_SETSIZE) { PyErr_SetString(PyExc_ValueError, "filedescriptor out of range in select()"); goto finally; } if (v > max) max = v;#endif /* _MSC_VER */ FD_SET(v, set); /* add object and its file descriptor to the list */ if (index >= FD_SETSIZE) { PyErr_SetString(PyExc_ValueError, "too many file descriptors in select()"); goto finally; } fd2obj[index].obj = o; fd2obj[index].fd = v; fd2obj[index].sentinel = 0; fd2obj[++index].sentinel = -1; } Py_DECREF(fast_seq); return max+1; finally: Py_XDECREF(o); Py_DECREF(fast_seq); return -1;} /* returns NULL and sets the Python exception if an error occurred */static PyObject *set2list(fd_set *set, pylist fd2obj[FD_SETSIZE + 1]){ int i, j, count=0; PyObject *list, *o; SOCKET fd; for (j = 0; fd2obj[j].sentinel >= 0; j++) { if (FD_ISSET(fd2obj[j].fd, set)) count++; } list = PyList_New(count); if (!list) return NULL; i = 0; for (j = 0; fd2obj[j].sentinel >= 0; j++) { fd = fd2obj[j].fd; if (FD_ISSET(fd, set)) {#ifndef _MSC_VER if (fd > FD_SETSIZE) { PyErr_SetString(PyExc_SystemError, "filedescriptor out of range returned in select()"); goto finally; }#endif o = fd2obj[j].obj; fd2obj[j].obj = NULL; /* transfer ownership */ if (PyList_SetItem(list, i, o) < 0) goto finally; i++; } } return list; finally: Py_DECREF(list); return NULL;} #undef SELECT_USES_HEAP#if FD_SETSIZE > 1024#define SELECT_USES_HEAP#endif /* FD_SETSIZE > 1024 */ static PyObject *select_select(PyObject *self, PyObject *args){#ifdef SELECT_USES_HEAP pylist *rfd2obj, *wfd2obj, *efd2obj;#else /* !SELECT_USES_HEAP */ /* XXX: All this should probably be implemented as follows: * - find the highest descriptor we're interested in * - add one * - that's the size * See: Stevens, APitUE, $12.5.1 */ pylist rfd2obj[FD_SETSIZE + 1]; pylist wfd2obj[FD_SETSIZE + 1]; pylist efd2obj[FD_SETSIZE + 1];#endif /* SELECT_USES_HEAP */ PyObject *ifdlist, *ofdlist, *efdlist; PyObject *ret = NULL; PyObject *tout = Py_None; fd_set ifdset, ofdset, efdset; double timeout; struct timeval tv, *tvp; long seconds; int imax, omax, emax, max; int n; /* convert arguments */ if (!PyArg_UnpackTuple(args, "select", 3, 4, &ifdlist, &ofdlist, &efdlist, &tout)) return NULL; if (tout == Py_None) tvp = (struct timeval *)0; else if (!PyNumber_Check(tout)) { PyErr_SetString(PyExc_TypeError, "timeout must be a float or None"); return NULL; } else { timeout = PyFloat_AsDouble(tout); if (timeout == -1 && PyErr_Occurred()) return NULL; if (timeout > (double)LONG_MAX) { PyErr_SetString(PyExc_OverflowError, "timeout period too long"); return NULL; } seconds = (long)timeout; timeout = timeout - (double)seconds; tv.tv_sec = seconds; tv.tv_usec = (long)(timeout*1000000.0); tvp = &tv; } #ifdef SELECT_USES_HEAP /* Allocate memory for the lists */ rfd2obj = PyMem_NEW(pylist, FD_SETSIZE + 1); wfd2obj = PyMem_NEW(pylist, FD_SETSIZE + 1); efd2obj = PyMem_NEW(pylist, FD_SETSIZE + 1); if (rfd2obj == NULL || wfd2obj == NULL || efd2obj == NULL) { if (rfd2obj) PyMem_DEL(rfd2obj); if (wfd2obj) PyMem_DEL(wfd2obj); if (efd2obj) PyMem_DEL(efd2obj); return PyErr_NoMemory(); }#endif /* SELECT_USES_HEAP */ /* Convert sequences to fd_sets, and get maximum fd number * propagates the Python exception set in seq2set() */ rfd2obj[0].sentinel = -1; wfd2obj[0].sentinel = -1; efd2obj[0].sentinel = -1; if ((imax=seq2set(ifdlist, &ifdset, rfd2obj)) < 0) goto finally; if ((omax=seq2set(ofdlist, &ofdset, wfd2obj)) < 0) goto finally; if ((emax=seq2set(efdlist, &efdset, efd2obj)) < 0) goto finally; max = imax; if (omax > max) max = omax; if (emax > max) max = emax; Py_BEGIN_ALLOW_THREADS n = select(max, &ifdset, &ofdset, &efdset, tvp); Py_END_ALLOW_THREADS #ifdef MS_WINDOWS if (n == SOCKET_ERROR) { PyErr_SetExcFromWindowsErr(SelectError, WSAGetLastError()); }#else if (n < 0) { PyErr_SetFromErrno(SelectError); }#endif else if (n == 0) { /* optimization */ ifdlist = PyList_New(0); if (ifdlist) { ret = PyTuple_Pack(3, ifdlist, ifdlist, ifdlist); Py_DECREF(ifdlist); } } else { /* any of these three calls can raise an exception. it's more convenient to test for this after all three calls... but is that acceptable? */ ifdlist = set2list(&ifdset, rfd2obj); ofdlist = set2list(&ofdset, wfd2obj); efdlist = set2list(&efdset, efd2obj); if (PyErr_Occurred()) ret = NULL; else ret = PyTuple_Pack(3, ifdlist, ofdlist, efdlist); Py_DECREF(ifdlist); Py_DECREF(ofdlist); Py_DECREF(efdlist); } finally: reap_obj(rfd2obj); reap_obj(wfd2obj); reap_obj(efd2obj);#ifdef SELECT_USES_HEAP PyMem_DEL(rfd2obj); PyMem_DEL(wfd2obj); PyMem_DEL(efd2obj);#endif /* SELECT_USES_HEAP */ return ret;} #if defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL)/* * poll() support */ typedef struct { PyObject_HEAD PyObject *dict; int ufd_uptodate; int ufd_len; struct pollfd *ufds;} pollObject; static PyTypeObject poll_Type; /* Update the malloc'ed array of pollfds to match the dictionary contained within a pollObject. Return 1 on success, 0 on an error.*/ static intupdate_ufd_array(pollObject *self){ Py_ssize_t i, pos; PyObject *key, *value; self->ufd_len = PyDict_Size(self->dict); PyMem_Resize(self->ufds, struct pollfd, self->ufd_len); if (self->ufds == NULL) { PyErr_NoMemory(); return 0; } i = pos = 0; while (PyDict_Next(self->dict, &pos, &key, &value)) { self->ufds[i].fd = PyInt_AsLong(key); self->ufds[i].events = (short)PyInt_AsLong(value); i++; } self->ufd_uptodate = 1; return 1;} PyDoc_STRVAR(poll_register_doc,"register(fd [, eventmask] ) -> None\n\n\Register a file descriptor with the polling object.\n\fd -- either an integer, or an object with a fileno() method returning an\n\ int.\n\events -- an optional bitmask describing the type of events to check for"); static PyObject *poll_register(pollObject *self, PyObject *args) { PyObject *o, *key, *value; int fd, events = POLLIN | POLLPRI | POLLOUT; int err; if (!PyArg_ParseTuple(args, "O|i:register", &o, &events)) { return NULL; } fd = PyObject_AsFileDescriptor(o); if (fd == -1) return NULL; /* Add entry to the internal dictionary: the key is the file descriptor, and the value is the event mask. */ key = PyInt_FromLong(fd); if (key == NULL) return NULL; value = PyInt_FromLong(events); if (value == NULL) { Py_DECREF(key); return NULL; } err = PyDict_SetItem(self->dict, key, value); Py_DECREF(key); Py_DECREF(value); if (err < 0) return NULL; self->ufd_uptodate = 0; Py_INCREF(Py_None); return Py_None;} PyDoc_STRVAR(poll_unregister_doc,"unregister(fd) -> None\n\n\Remove a file descriptor being tracked by the polling object."); static PyObject *poll_unregister(pollObject *self, PyObject *o) { PyObject *key; int fd; fd = PyObject_AsFileDescriptor( o ); if (fd == -1) return NULL; /* Check whether the fd is already in the array */ key = PyInt_FromLong(fd); if (key == NULL) return NULL; if (PyDict_DelItem(self->dict, key) == -1) { Py_DECREF(key); /* This will simply raise the KeyError set by PyDict_DelItem if the file descriptor isn't registered. */ return NULL; } Py_DECREF(key); self->ufd_uptodate = 0; Py_INCREF(Py_None); return Py_None;} PyDoc_STRVAR(poll_poll_doc,"poll( [timeout] ) -> list of (fd, event) 2-tuples\n\n\Polls the set of registered file descriptors, returning a list containing \n\any descriptors that have events or errors to report."); static PyObject *poll_poll(pollObject *self, PyObject *args) { PyObject *result_list = NULL, *tout = NULL; int timeout = 0, poll_result, i, j; PyObject *value = NULL, *num = NULL; if (!PyArg_UnpackTuple(args, "poll", 0, 1, &tout)) { return NULL; } /* Check values for timeout */ if (tout == NULL || tout == Py_None) timeout = -1; else if (!PyNumber_Check(tout)) { PyErr_SetString(PyExc_TypeError, "timeout must be an integer or None"); return NULL; } else { tout = PyNumber_Int(tout); if (!tout) return NULL; timeout = PyInt_AsLong(tout); Py_DECREF(tout); if (timeout == -1 && PyErr_Occurred()) return NULL; } /* Ensure the ufd array is up to date */ if (!self->ufd_uptodate) if (update_ufd_array(self) == 0) return NULL; /* call poll() */ Py_BEGIN_ALLOW_THREADS; poll_result = poll(self->ufds, self->ufd_len, timeout); Py_END_ALLOW_THREADS; if (poll_result < 0) { PyErr_SetFromErrno(SelectError); return NULL; } /* build the result list */ result_list = PyList_New(poll_result); if (!result_list) return NULL; else {Lines 1–500 of 734. Load more
/* select - Module containing unix select(2) call. Under Unix, the file descriptors are small integers. Under Win32, select only exists for sockets, and sockets may have any value except INVALID_SOCKET. Under BeOS, we suffer the same dichotomy as Win32; sockets can be anything >= 0. */ #include "Python.h" #ifdef __APPLE__ /* Perform runtime testing for a broken poll on OSX to make it easier * to use the same binary on multiple releases of the OS. */ #undef HAVE_BROKEN_POLL #endif /* Windows #defines FD_SETSIZE to 64 if FD_SETSIZE isn't already defined. 64 is too small (too many people have bumped into that limit). Here we boost it. Users who want even more than the boosted limit should #define FD_SETSIZE higher before this; e.g., via compiler /D switch. */ #if defined(MS_WINDOWS) && !defined(FD_SETSIZE) #define FD_SETSIZE 512 #endif #if defined(HAVE_POLL_H) #include <poll.h> #elif defined(HAVE_SYS_POLL_H) #include <sys/poll.h> #endif #ifdef __sgi /* This is missing from unistd.h */ extern void bzero(void *, int); #endif #ifdef HAVE_SYS_TYPES_H #include <sys/types.h> #endif #if defined(PYOS_OS2) && !defined(PYCC_GCC) #include <sys/time.h> #include <utils.h> #endif #ifdef MS_WINDOWS # include <winsock.h> #else # define SOCKET int # ifdef __BEOS__ # include <net/socket.h> # elif defined(__VMS) # include <socket.h> # endif #endif static PyObject *SelectError; /* list of Python objects and their file descriptor */ typedef struct { PyObject *obj; /* owned reference */ SOCKET fd; int sentinel; /* -1 == sentinel */ } pylist; static void reap_obj(pylist fd2obj[FD_SETSIZE + 1]) { int i; for (i = 0; i < FD_SETSIZE + 1 && fd2obj[i].sentinel >= 0; i++) { Py_XDECREF(fd2obj[i].obj); fd2obj[i].obj = NULL; } fd2obj[0].sentinel = -1; } /* returns -1 and sets the Python exception if an error occurred, otherwise returns a number >= 0 */ static int seq2set(PyObject *seq, fd_set *set, pylist fd2obj[FD_SETSIZE + 1]) { int i; int max = -1; int index = 0; int len = -1; PyObject* fast_seq = NULL; PyObject* o = NULL; fd2obj[0].obj = (PyObject*)0; /* set list to zero size */ FD_ZERO(set); fast_seq=PySequence_Fast(seq, "arguments 1-3 must be sequences"); if (!fast_seq) return -1; len = PySequence_Fast_GET_SIZE(fast_seq); for (i = 0; i < len; i++) { SOCKET v; /* any intervening fileno() calls could decr this refcnt */ if (!(o = PySequence_Fast_GET_ITEM(fast_seq, i))) return -1; Py_INCREF(o); v = PyObject_AsFileDescriptor( o ); if (v == -1) goto finally; #if defined(_MSC_VER) max = 0; /* not used for Win32 */ #else /* !_MSC_VER */ if (v < 0 || v >= FD_SETSIZE) { PyErr_SetString(PyExc_ValueError, "filedescriptor out of range in select()"); goto finally; } if (v > max) max = v; #endif /* _MSC_VER */ FD_SET(v, set); /* add object and its file descriptor to the list */ if (index >= FD_SETSIZE) { PyErr_SetString(PyExc_ValueError, "too many file descriptors in select()"); goto finally; } fd2obj[index].obj = o; fd2obj[index].fd = v; fd2obj[index].sentinel = 0; fd2obj[++index].sentinel = -1; } Py_DECREF(fast_seq); return max+1; finally: Py_XDECREF(o); Py_DECREF(fast_seq); return -1; } /* returns NULL and sets the Python exception if an error occurred */ static PyObject * set2list(fd_set *set, pylist fd2obj[FD_SETSIZE + 1]) { int i, j, count=0; PyObject *list, *o; SOCKET fd; for (j = 0; fd2obj[j].sentinel >= 0; j++) { if (FD_ISSET(fd2obj[j].fd, set)) count++; } list = PyList_New(count); if (!list) return NULL; i = 0; for (j = 0; fd2obj[j].sentinel >= 0; j++) { fd = fd2obj[j].fd; if (FD_ISSET(fd, set)) { #ifndef _MSC_VER if (fd > FD_SETSIZE) { PyErr_SetString(PyExc_SystemError, "filedescriptor out of range returned in select()"); goto finally; } #endif o = fd2obj[j].obj; fd2obj[j].obj = NULL; /* transfer ownership */ if (PyList_SetItem(list, i, o) < 0) goto finally; i++; } } return list; finally: Py_DECREF(list); return NULL; } #undef SELECT_USES_HEAP #if FD_SETSIZE > 1024 #define SELECT_USES_HEAP #endif /* FD_SETSIZE > 1024 */ static PyObject * select_select(PyObject *self, PyObject *args) { #ifdef SELECT_USES_HEAP pylist *rfd2obj, *wfd2obj, *efd2obj; #else /* !SELECT_USES_HEAP */ /* XXX: All this should probably be implemented as follows: * - find the highest descriptor we're interested in * - add one * - that's the size * See: Stevens, APitUE, $12.5.1 */ pylist rfd2obj[FD_SETSIZE + 1]; pylist wfd2obj[FD_SETSIZE + 1]; pylist efd2obj[FD_SETSIZE + 1]; #endif /* SELECT_USES_HEAP */ PyObject *ifdlist, *ofdlist, *efdlist; PyObject *ret = NULL; PyObject *tout = Py_None; fd_set ifdset, ofdset, efdset; double timeout; struct timeval tv, *tvp; long seconds; int imax, omax, emax, max; int n; /* convert arguments */ if (!PyArg_UnpackTuple(args, "select", 3, 4, &ifdlist, &ofdlist, &efdlist, &tout)) return NULL; if (tout == Py_None) tvp = (struct timeval *)0; else if (!PyNumber_Check(tout)) { PyErr_SetString(PyExc_TypeError, "timeout must be a float or None"); return NULL; } else { timeout = PyFloat_AsDouble(tout); if (timeout == -1 && PyErr_Occurred()) return NULL; if (timeout > (double)LONG_MAX) { PyErr_SetString(PyExc_OverflowError, "timeout period too long"); return NULL; } seconds = (long)timeout; timeout = timeout - (double)seconds; tv.tv_sec = seconds; tv.tv_usec = (long)(timeout*1000000.0); tvp = &tv; } #ifdef SELECT_USES_HEAP /* Allocate memory for the lists */ rfd2obj = PyMem_NEW(pylist, FD_SETSIZE + 1); wfd2obj = PyMem_NEW(pylist, FD_SETSIZE + 1); efd2obj = PyMem_NEW(pylist, FD_SETSIZE + 1); if (rfd2obj == NULL || wfd2obj == NULL || efd2obj == NULL) { if (rfd2obj) PyMem_DEL(rfd2obj); if (wfd2obj) PyMem_DEL(wfd2obj); if (efd2obj) PyMem_DEL(efd2obj); return PyErr_NoMemory(); } #endif /* SELECT_USES_HEAP */ /* Convert sequences to fd_sets, and get maximum fd number * propagates the Python exception set in seq2set() */ rfd2obj[0].sentinel = -1; wfd2obj[0].sentinel = -1; efd2obj[0].sentinel = -1; if ((imax=seq2set(ifdlist, &ifdset, rfd2obj)) < 0) goto finally; if ((omax=seq2set(ofdlist, &ofdset, wfd2obj)) < 0) goto finally; if ((emax=seq2set(efdlist, &efdset, efd2obj)) < 0) goto finally; max = imax; if (omax > max) max = omax; if (emax > max) max = emax; Py_BEGIN_ALLOW_THREADS n = select(max, &ifdset, &ofdset, &efdset, tvp); Py_END_ALLOW_THREADS #ifdef MS_WINDOWS if (n == SOCKET_ERROR) { PyErr_SetExcFromWindowsErr(SelectError, WSAGetLastError()); } #else if (n < 0) { PyErr_SetFromErrno(SelectError); } #endif else if (n == 0) { /* optimization */ ifdlist = PyList_New(0); if (ifdlist) { ret = PyTuple_Pack(3, ifdlist, ifdlist, ifdlist); Py_DECREF(ifdlist); } } else { /* any of these three calls can raise an exception. it's more convenient to test for this after all three calls... but is that acceptable? */ ifdlist = set2list(&ifdset, rfd2obj); ofdlist = set2list(&ofdset, wfd2obj); efdlist = set2list(&efdset, efd2obj); if (PyErr_Occurred()) ret = NULL; else ret = PyTuple_Pack(3, ifdlist, ofdlist, efdlist); Py_DECREF(ifdlist); Py_DECREF(ofdlist); Py_DECREF(efdlist); } finally: reap_obj(rfd2obj); reap_obj(wfd2obj); reap_obj(efd2obj); #ifdef SELECT_USES_HEAP PyMem_DEL(rfd2obj); PyMem_DEL(wfd2obj); PyMem_DEL(efd2obj); #endif /* SELECT_USES_HEAP */ return ret; } #if defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL) /* * poll() support */ typedef struct { PyObject_HEAD PyObject *dict; int ufd_uptodate; int ufd_len; struct pollfd *ufds; } pollObject; static PyTypeObject poll_Type; /* Update the malloc'ed array of pollfds to match the dictionary contained within a pollObject. Return 1 on success, 0 on an error. */ static int update_ufd_array(pollObject *self) { Py_ssize_t i, pos; PyObject *key, *value; self->ufd_len = PyDict_Size(self->dict); PyMem_Resize(self->ufds, struct pollfd, self->ufd_len); if (self->ufds == NULL) { PyErr_NoMemory(); return 0; } i = pos = 0; while (PyDict_Next(self->dict, &pos, &key, &value)) { self->ufds[i].fd = PyInt_AsLong(key); self->ufds[i].events = (short)PyInt_AsLong(value); i++; } self->ufd_uptodate = 1; return 1; } PyDoc_STRVAR(poll_register_doc, "register(fd [, eventmask] ) -> None\n\n\ Register a file descriptor with the polling object.\n\ fd -- either an integer, or an object with a fileno() method returning an\n\ int.\n\ events -- an optional bitmask describing the type of events to check for"); static PyObject * poll_register(pollObject *self, PyObject *args) { PyObject *o, *key, *value; int fd, events = POLLIN | POLLPRI | POLLOUT; int err; if (!PyArg_ParseTuple(args, "O|i:register", &o, &events)) { return NULL; } fd = PyObject_AsFileDescriptor(o); if (fd == -1) return NULL; /* Add entry to the internal dictionary: the key is the file descriptor, and the value is the event mask. */ key = PyInt_FromLong(fd); if (key == NULL) return NULL; value = PyInt_FromLong(events); if (value == NULL) { Py_DECREF(key); return NULL; } err = PyDict_SetItem(self->dict, key, value); Py_DECREF(key); Py_DECREF(value); if (err < 0) return NULL; self->ufd_uptodate = 0; Py_INCREF(Py_None); return Py_None; } PyDoc_STRVAR(poll_unregister_doc, "unregister(fd) -> None\n\n\ Remove a file descriptor being tracked by the polling object."); static PyObject * poll_unregister(pollObject *self, PyObject *o) { PyObject *key; int fd; fd = PyObject_AsFileDescriptor( o ); if (fd == -1) return NULL; /* Check whether the fd is already in the array */ key = PyInt_FromLong(fd); if (key == NULL) return NULL; if (PyDict_DelItem(self->dict, key) == -1) { Py_DECREF(key); /* This will simply raise the KeyError set by PyDict_DelItem if the file descriptor isn't registered. */ return NULL; } Py_DECREF(key); self->ufd_uptodate = 0; Py_INCREF(Py_None); return Py_None; } PyDoc_STRVAR(poll_poll_doc, "poll( [timeout] ) -> list of (fd, event) 2-tuples\n\n\ Polls the set of registered file descriptors, returning a list containing \n\ any descriptors that have events or errors to report."); static PyObject * poll_poll(pollObject *self, PyObject *args) { PyObject *result_list = NULL, *tout = NULL; int timeout = 0, poll_result, i, j; PyObject *value = NULL, *num = NULL; if (!PyArg_UnpackTuple(args, "poll", 0, 1, &tout)) { return NULL; } /* Check values for timeout */ if (tout == NULL || tout == Py_None) timeout = -1; else if (!PyNumber_Check(tout)) { PyErr_SetString(PyExc_TypeError, "timeout must be an integer or None"); return NULL; } else { tout = PyNumber_Int(tout); if (!tout) return NULL; timeout = PyInt_AsLong(tout); Py_DECREF(tout); if (timeout == -1 && PyErr_Occurred()) return NULL; } /* Ensure the ufd array is up to date */ if (!self->ufd_uptodate) if (update_ufd_array(self) == 0) return NULL; /* call poll() */ Py_BEGIN_ALLOW_THREADS; poll_result = poll(self->ufds, self->ufd_len, timeout); Py_END_ALLOW_THREADS; if (poll_result < 0) { PyErr_SetFromErrno(SelectError); return NULL; } /* build the result list */ result_list = PyList_New(poll_result); if (!result_list) return NULL; else {