diff --git a/Modules/selectmodule.c b/Modules/selectmodule.c index d234d504cb5167..327a079b5e97a3 100644 --- a/Modules/selectmodule.c +++ b/Modules/selectmodule.c @@ -790,12 +790,16 @@ poll_dealloc(PyObject *op) #ifdef HAVE_SYS_DEVPOLL_H static PyMethodDef devpoll_methods[]; +#define DEVPOLL_IN_BUFFER_SIZE 128 +#define DEVPOLL_MAX_OUT_BUFFER_SIZE 1024 + typedef struct { PyObject_HEAD int fd_devpoll; - int max_n_fds; int n_fds; + int out_size; struct pollfd *fds; + struct pollfd *out_fds; } devpollObject; #define devpollObject_CAST(op) ((devpollObject *)(op)) @@ -848,7 +852,7 @@ internal_devpoll_register(devpollObject *self, int fd, self->fds[self->n_fds].fd = fd; self->fds[self->n_fds].events = POLLREMOVE; - if (++self->n_fds == self->max_n_fds) { + if (++self->n_fds == DEVPOLL_IN_BUFFER_SIZE) { if (devpoll_flush(self)) return NULL; } @@ -857,7 +861,7 @@ internal_devpoll_register(devpollObject *self, int fd, self->fds[self->n_fds].fd = fd; self->fds[self->n_fds].events = (signed short)events; - if (++self->n_fds == self->max_n_fds) { + if (++self->n_fds == DEVPOLL_IN_BUFFER_SIZE) { if (devpoll_flush(self)) return NULL; } @@ -929,7 +933,7 @@ select_devpoll_unregister_impl(devpollObject *self, int fd) self->fds[self->n_fds].fd = fd; self->fds[self->n_fds].events = POLLREMOVE; - if (++self->n_fds == self->max_n_fds) { + if (++self->n_fds == DEVPOLL_IN_BUFFER_SIZE) { if (devpoll_flush(self)) return NULL; } @@ -989,8 +993,8 @@ select_devpoll_poll_impl(devpollObject *self, PyObject *timeout_obj) if (devpoll_flush(self)) return NULL; - dvp.dp_fds = self->fds; - dvp.dp_nfds = self->max_n_fds; + dvp.dp_fds = self->out_fds; + dvp.dp_nfds = self->out_size; dvp.dp_timeout = (int)ms; if (timeout >= 0) { @@ -1034,8 +1038,8 @@ select_devpoll_poll_impl(devpollObject *self, PyObject *timeout_obj) return NULL; for (i = 0; i < poll_result; i++) { - num1 = PyLong_FromLong(self->fds[i].fd); - num2 = PyLong_FromLong(self->fds[i].revents); + num1 = PyLong_FromLong(self->out_fds[i].fd); + num2 = PyLong_FromLong(self->out_fds[i].revents); if ((num1 == NULL) || (num2 == NULL)) { Py_XDECREF(num1); Py_XDECREF(num2); @@ -1128,12 +1132,12 @@ static devpollObject * newDevPollObject(PyObject *module) { devpollObject *self; - int fd_devpoll, limit_result; - struct pollfd *fds; + int fd_devpoll, limit_result, out_size; + struct pollfd *fds, *out_fds; struct rlimit limit; /* - ** If we try to process more that getrlimit() + ** If we try to process more than getrlimit() ** fds, the kernel will give an error, so ** we set the limit here. It is a dynamic ** value, because we can change rlimit() anytime. @@ -1144,27 +1148,46 @@ newDevPollObject(PyObject *module) return NULL; } + /* + ** If the limit is too high (or RLIM_INFINITY), we might + ** allocate huge amounts of memory or even fail to allocate. + */ + out_size = limit.rlim_cur; + if (out_size > DEVPOLL_MAX_OUT_BUFFER_SIZE) { + out_size = DEVPOLL_MAX_OUT_BUFFER_SIZE; + } + fd_devpoll = _Py_open("/dev/poll", O_RDWR); if (fd_devpoll == -1) return NULL; - fds = PyMem_NEW(struct pollfd, limit.rlim_cur); + fds = PyMem_NEW(struct pollfd, DEVPOLL_IN_BUFFER_SIZE); if (fds == NULL) { close(fd_devpoll); PyErr_NoMemory(); return NULL; } + out_fds = PyMem_NEW(struct pollfd, out_size); + if (fds == NULL) { + close(fd_devpoll); + PyMem_Free(fds); + PyErr_NoMemory(); + return NULL; + } + self = PyObject_New(devpollObject, get_select_state(module)->devpoll_Type); if (self == NULL) { close(fd_devpoll); PyMem_Free(fds); + PyMem_Free(out_fds); return NULL; } self->fd_devpoll = fd_devpoll; - self->max_n_fds = limit.rlim_cur; self->n_fds = 0; self->fds = fds; + self->out_size = out_size; + self->out_fds = out_fds; return self; } @@ -1176,6 +1199,7 @@ devpoll_dealloc(PyObject *op) PyTypeObject *type = Py_TYPE(self); (void)devpoll_internal_close(self); PyMem_Free(self->fds); + PyMem_Free(self->out_fds); PyObject_Free(self); Py_DECREF(type); }