Skip to content
50 changes: 37 additions & 13 deletions Modules/selectmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down Expand Up @@ -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;
}
Expand All @@ -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;
}
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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.
Expand All @@ -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) {
Comment thread
kulikjak marked this conversation as resolved.
Outdated
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;
}
Expand All @@ -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);
}
Expand Down
Loading