for (i = 0, j = 0; j < poll_result; j++) { /* skip to the next fired descriptor */ while (!self->ufds[i].revents) { i++; } /* if we hit a NULL return, set value to NULL and break out of loop; code at end will clean up result_list */ value = PyTuple_New(2); if (value == NULL) goto error; num = PyInt_FromLong(self->ufds[i].fd); if (num == NULL) { Py_DECREF(value); goto error; } PyTuple_SET_ITEM(value, 0, num); /* The &0xffff is a workaround for AIX. 'revents' is a 16-bit short, and IBM assigned POLLNVAL to be 0x8000, so the conversion to int results in a negative number. See SF bug #923315. */ num = PyInt_FromLong(self->ufds[i].revents & 0xffff); if (num == NULL) { Py_DECREF(value); goto error; } PyTuple_SET_ITEM(value, 1, num); if ((PyList_SetItem(result_list, j, value)) == -1) { Py_DECREF(value); goto error; } i++; } } return result_list; error: Py_DECREF(result_list); return NULL;} static PyMethodDef poll_methods[] = { {"register", (PyCFunction)poll_register, METH_VARARGS, poll_register_doc}, {"unregister", (PyCFunction)poll_unregister, METH_O, poll_unregister_doc}, {"poll", (PyCFunction)poll_poll, METH_VARARGS, poll_poll_doc}, {NULL, NULL} /* sentinel */}; static pollObject *newPollObject(void){ pollObject *self; self = PyObject_New(pollObject, &poll_Type); if (self == NULL) return NULL; /* ufd_uptodate is a Boolean, denoting whether the array pointed to by ufds matches the contents of the dictionary. */ self->ufd_uptodate = 0; self->ufds = NULL; self->dict = PyDict_New(); if (self->dict == NULL) { Py_DECREF(self); return NULL; } return self;} static voidpoll_dealloc(pollObject *self){ if (self->ufds != NULL) PyMem_DEL(self->ufds); Py_XDECREF(self->dict); PyObject_Del(self);} static PyObject *poll_getattr(pollObject *self, char *name){ return Py_FindMethod(poll_methods, (PyObject *)self, name);} static PyTypeObject poll_Type = { /* The ob_type field must be initialized in the module init function * to be portable to Windows without using C++. */ PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "select.poll", /*tp_name*/ sizeof(pollObject), /*tp_basicsize*/ 0, /*tp_itemsize*/ /* methods */ (destructor)poll_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ (getattrfunc)poll_getattr, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash*/}; PyDoc_STRVAR(poll_doc,"Returns a polling object, which supports registering and\n\unregistering file descriptors, and then polling them for I/O events."); static PyObject *select_poll(PyObject *self, PyObject *unused){ return (PyObject *)newPollObject();} #ifdef __APPLE__/* * On some systems poll() sets errno on invalid file descriptors. We test * for this at runtime because this bug may be fixed or introduced between * OS releases. */static int select_have_broken_poll(void){ int poll_test; int filedes[2]; struct pollfd poll_struct = { 0, POLLIN|POLLPRI|POLLOUT, 0 }; /* Create a file descriptor to make invalid */ if (pipe(filedes) < 0) { return 1; } poll_struct.fd = filedes[0]; close(filedes[0]); close(filedes[1]); poll_test = poll(&poll_struct, 1, 0); if (poll_test < 0) { return 1; } else if (poll_test == 0 && poll_struct.revents != POLLNVAL) { return 1; } return 0;}#endif /* __APPLE__ */ #endif /* HAVE_POLL */ PyDoc_STRVAR(select_doc,"select(rlist, wlist, xlist[, timeout]) -> (rlist, wlist, xlist)\n\\n\Wait until one or more file descriptors are ready for some kind of I/O.\n\The first three arguments are sequences of file descriptors to be waited for:\n\rlist -- wait until ready for reading\n\wlist -- wait until ready for writing\n\xlist -- wait for an ``exceptional condition''\n\If only one kind of condition is required, pass [] for the other lists.\n\A file descriptor is either a socket or file object, or a small integer\n\gotten from a fileno() method call on one of those.\n\\n\The optional 4th argument specifies a timeout in seconds; it may be\n\a floating point number to specify fractions of seconds. If it is absent\n\or None, the call will never time out.\n\\n\The return value is a tuple of three lists corresponding to the first three\n\arguments; each contains the subset of the corresponding file descriptors\n\that are ready.\n\\n\*** IMPORTANT NOTICE ***\n\On Windows and OpenVMS, only sockets are supported; on Unix, all file descriptors."); static PyMethodDef select_methods[] = { {"select", select_select, METH_VARARGS, select_doc},#if defined(HAVE_POLL) {"poll", select_poll, METH_NOARGS, poll_doc},#endif /* HAVE_POLL */ {0, 0}, /* sentinel */}; PyDoc_STRVAR(module_doc,"This module supports asynchronous I/O on multiple file descriptors.\n\\n\*** IMPORTANT NOTICE ***\n\On Windows and OpenVMS, only sockets are supported; on Unix, all file descriptors."); PyMODINIT_FUNCinitselect(void){ PyObject *m; m = Py_InitModule3("select", select_methods, module_doc); if (m == NULL) return; SelectError = PyErr_NewException("select.error", NULL, NULL); Py_INCREF(SelectError); PyModule_AddObject(m, "error", SelectError);#if defined(HAVE_POLL) #ifdef __APPLE__ if (select_have_broken_poll()) { if (PyObject_DelAttrString(m, "poll") == -1) { PyErr_Clear(); } } else {#else {#endif poll_Type.ob_type = &PyType_Type; PyModule_AddIntConstant(m, "POLLIN", POLLIN); PyModule_AddIntConstant(m, "POLLPRI", POLLPRI); PyModule_AddIntConstant(m, "POLLOUT", POLLOUT); PyModule_AddIntConstant(m, "POLLERR", POLLERR); PyModule_AddIntConstant(m, "POLLHUP", POLLHUP); PyModule_AddIntConstant(m, "POLLNVAL", POLLNVAL); #ifdef POLLRDNORM PyModule_AddIntConstant(m, "POLLRDNORM", POLLRDNORM);#endif#ifdef POLLRDBAND PyModule_AddIntConstant(m, "POLLRDBAND", POLLRDBAND);#endif#ifdef POLLWRNORM PyModule_AddIntConstant(m, "POLLWRNORM", POLLWRNORM);#endif#ifdef POLLWRBAND PyModule_AddIntConstant(m, "POLLWRBAND", POLLWRBAND);#endif#ifdef POLLMSG PyModule_AddIntConstant(m, "POLLMSG", POLLMSG);#endif }#endif /* HAVE_POLL */}Lines 501–734 of 734. Previous lines
for (i = 0, j = 0; j < poll_result; j++) { /* skip to the next fired descriptor */ while (!self->ufds[i].revents) { i++; } /* if we hit a NULL return, set value to NULL and break out of loop; code at end will clean up result_list */ value = PyTuple_New(2); if (value == NULL) goto error; num = PyInt_FromLong(self->ufds[i].fd); if (num == NULL) { Py_DECREF(value); goto error; } PyTuple_SET_ITEM(value, 0, num); /* The &0xffff is a workaround for AIX. 'revents' is a 16-bit short, and IBM assigned POLLNVAL to be 0x8000, so the conversion to int results in a negative number. See SF bug #923315. */ num = PyInt_FromLong(self->ufds[i].revents & 0xffff); if (num == NULL) { Py_DECREF(value); goto error; } PyTuple_SET_ITEM(value, 1, num); if ((PyList_SetItem(result_list, j, value)) == -1) { Py_DECREF(value); goto error; } i++; } } return result_list; error: Py_DECREF(result_list); return NULL; } static PyMethodDef poll_methods[] = { {"register", (PyCFunction)poll_register, METH_VARARGS, poll_register_doc}, {"unregister", (PyCFunction)poll_unregister, METH_O, poll_unregister_doc}, {"poll", (PyCFunction)poll_poll, METH_VARARGS, poll_poll_doc}, {NULL, NULL} /* sentinel */ }; static pollObject * newPollObject(void) { pollObject *self; self = PyObject_New(pollObject, &poll_Type); if (self == NULL) return NULL; /* ufd_uptodate is a Boolean, denoting whether the array pointed to by ufds matches the contents of the dictionary. */ self->ufd_uptodate = 0; self->ufds = NULL; self->dict = PyDict_New(); if (self->dict == NULL) { Py_DECREF(self); return NULL; } return self; } static void poll_dealloc(pollObject *self) { if (self->ufds != NULL) PyMem_DEL(self->ufds); Py_XDECREF(self->dict); PyObject_Del(self); } static PyObject * poll_getattr(pollObject *self, char *name) { return Py_FindMethod(poll_methods, (PyObject *)self, name); } static PyTypeObject poll_Type = { /* The ob_type field must be initialized in the module init function * to be portable to Windows without using C++. */ PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "select.poll", /*tp_name*/ sizeof(pollObject), /*tp_basicsize*/ 0, /*tp_itemsize*/ /* methods */ (destructor)poll_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ (getattrfunc)poll_getattr, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash*/ }; PyDoc_STRVAR(poll_doc, "Returns a polling object, which supports registering and\n\ unregistering file descriptors, and then polling them for I/O events."); static PyObject * select_poll(PyObject *self, PyObject *unused) { return (PyObject *)newPollObject(); } #ifdef __APPLE__ /* * On some systems poll() sets errno on invalid file descriptors. We test * for this at runtime because this bug may be fixed or introduced between * OS releases. */ static int select_have_broken_poll(void) { int poll_test; int filedes[2]; struct pollfd poll_struct = { 0, POLLIN|POLLPRI|POLLOUT, 0 }; /* Create a file descriptor to make invalid */ if (pipe(filedes) < 0) { return 1; } poll_struct.fd = filedes[0]; close(filedes[0]); close(filedes[1]); poll_test = poll(&poll_struct, 1, 0); if (poll_test < 0) { return 1; } else if (poll_test == 0 && poll_struct.revents != POLLNVAL) { return 1; } return 0; } #endif /* __APPLE__ */ #endif /* HAVE_POLL */ PyDoc_STRVAR(select_doc, "select(rlist, wlist, xlist[, timeout]) -> (rlist, wlist, xlist)\n\ \n\ Wait until one or more file descriptors are ready for some kind of I/O.\n\ The first three arguments are sequences of file descriptors to be waited for:\n\ rlist -- wait until ready for reading\n\ wlist -- wait until ready for writing\n\ xlist -- wait for an ``exceptional condition''\n\ If only one kind of condition is required, pass [] for the other lists.\n\ A file descriptor is either a socket or file object, or a small integer\n\ gotten from a fileno() method call on one of those.\n\ \n\ The optional 4th argument specifies a timeout in seconds; it may be\n\ a floating point number to specify fractions of seconds. If it is absent\n\ or None, the call will never time out.\n\ \n\ The return value is a tuple of three lists corresponding to the first three\n\ arguments; each contains the subset of the corresponding file descriptors\n\ that are ready.\n\ \n\ *** IMPORTANT NOTICE ***\n\ On Windows and OpenVMS, only sockets are supported; on Unix, all file descriptors."); static PyMethodDef select_methods[] = { {"select", select_select, METH_VARARGS, select_doc}, #if defined(HAVE_POLL) {"poll", select_poll, METH_NOARGS, poll_doc}, #endif /* HAVE_POLL */ {0, 0}, /* sentinel */ }; PyDoc_STRVAR(module_doc, "This module supports asynchronous I/O on multiple file descriptors.\n\ \n\ *** IMPORTANT NOTICE ***\n\ On Windows and OpenVMS, only sockets are supported; on Unix, all file descriptors."); PyMODINIT_FUNC initselect(void) { PyObject *m; m = Py_InitModule3("select", select_methods, module_doc); if (m == NULL) return; SelectError = PyErr_NewException("select.error", NULL, NULL); Py_INCREF(SelectError); PyModule_AddObject(m, "error", SelectError); #if defined(HAVE_POLL) #ifdef __APPLE__ if (select_have_broken_poll()) { if (PyObject_DelAttrString(m, "poll") == -1) { PyErr_Clear(); } } else { #else { #endif poll_Type.ob_type = &PyType_Type; PyModule_AddIntConstant(m, "POLLIN", POLLIN); PyModule_AddIntConstant(m, "POLLPRI", POLLPRI); PyModule_AddIntConstant(m, "POLLOUT", POLLOUT); PyModule_AddIntConstant(m, "POLLERR", POLLERR); PyModule_AddIntConstant(m, "POLLHUP", POLLHUP); PyModule_AddIntConstant(m, "POLLNVAL", POLLNVAL); #ifdef POLLRDNORM PyModule_AddIntConstant(m, "POLLRDNORM", POLLRDNORM); #endif #ifdef POLLRDBAND PyModule_AddIntConstant(m, "POLLRDBAND", POLLRDBAND); #endif #ifdef POLLWRNORM PyModule_AddIntConstant(m, "POLLWRNORM", POLLWRNORM); #endif #ifdef POLLWRBAND PyModule_AddIntConstant(m, "POLLWRBAND", POLLWRBAND); #endif #ifdef POLLMSG PyModule_AddIntConstant(m, "POLLMSG", POLLMSG); #endif } #endif /* HAVE_POLL */ }