Skip to content

Commit 082b121

Browse files
committed
unix/moduselect: register(): Allow to call with duplicate file descriptor.
Per CPython docs, "Registering a file descriptor that’s already registered is not an error, and has the same effect as registering the descriptor exactly once." https://docs.python.org/3/library/select.html#select.poll.register That's somewhat ambiguous, what's implemented here is that if fd si not yet registered, it is registered. Otherwise, the effect is equivalent to modify() method.
1 parent f2d532c commit 082b121

1 file changed

Lines changed: 21 additions & 16 deletions

File tree

unix/moduselect.c

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -47,35 +47,40 @@ typedef struct _mp_obj_poll_t {
4747
/// \method register(obj[, eventmask])
4848
STATIC mp_obj_t poll_register(uint n_args, const mp_obj_t *args) {
4949
mp_obj_poll_t *self = MP_OBJ_TO_PTR(args[0]);
50+
int fd = mp_obj_get_int(args[1]);
5051
mp_uint_t flags;
5152
if (n_args == 3) {
5253
flags = mp_obj_get_int(args[2]);
5354
} else {
5455
flags = POLLIN | POLLOUT;
5556
}
5657

57-
int i = 0;
58-
if (self->len < self->alloc) {
59-
i = self->len++;
60-
} else {
61-
struct pollfd *entries = self->entries;
62-
for (i = 0; i < self->len; i++, entries++) {
63-
if (entries->fd == -1) {
64-
break;
65-
}
58+
struct pollfd *free_slot = NULL;
59+
60+
struct pollfd *entry = self->entries;
61+
for (int i = 0; i < self->len; i++, entry++) {
62+
int entry_fd = entry->fd;
63+
if (entry_fd == fd) {
64+
entry->events = flags;
65+
return mp_const_false;
66+
}
67+
if (entry_fd == -1) {
68+
free_slot = entry;
6669
}
67-
if (entries->fd != -1) {
68-
i = self->len++;
70+
}
71+
72+
if (free_slot == NULL) {
73+
if (self->len >= self->alloc) {
6974
self->entries = m_renew(struct pollfd, self->entries, self->alloc, self->alloc + 4);
7075
self->alloc += 4;
7176
}
77+
free_slot = &self->entries[self->len++];
7278
}
7379

74-
self->entries[i].fd = mp_obj_get_int(args[1]);
75-
self->entries[i].events = flags;
76-
self->entries[i].revents = 0;
77-
78-
return mp_const_none;
80+
free_slot->fd = fd;
81+
free_slot->events = flags;
82+
free_slot->revents = 0;
83+
return mp_const_true;
7984
}
8085
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(poll_register_obj, 2, 3, poll_register);
8186

0 commit comments

Comments
 (0)