Skip to content
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
split the in and out buffer into two with different sizes
  • Loading branch information
kulikjak committed Jul 30, 2025
commit f949dea21f419f431f196796925a1231a1c0e697
49 changes: 32 additions & 17 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,8 +1132,8 @@ 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;

/*
Expand All @@ -1145,35 +1149,45 @@ newDevPollObject(PyObject *module)
}

/*
** If the limit is too high (or RLIM_INFINITY), we might allocate huge
** amounts of memory (or even fail to allocate). Because of that, we limit
** the number of allocated structs to 2^18 (which is ~4MB of memory).
** If the limit is too high (or RLIM_INFINITY), we might
** allocate huge amounts of memory or even fail to allocate.
*/
if (limit.rlim_cur > (rlim_t)262144) {
limit.rlim_cur = (rlim_t)262144;
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->max_n_fds = out_size;
self->n_fds = 0;
self->fds = fds;
self->out_fds = out_fds;

return self;
}
Expand All @@ -1185,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