Skip to content

fix(socketcan): support socket file descriptors over 1023#2057

Open
SAY-5 wants to merge 3 commits into
hardbyte:mainfrom
SAY-5:fix/socketcan-high-fd
Open

fix(socketcan): support socket file descriptors over 1023#2057
SAY-5 wants to merge 3 commits into
hardbyte:mainfrom
SAY-5:fix/socketcan-high-fd

Conversation

@SAY-5
Copy link
Copy Markdown
Contributor

@SAY-5 SAY-5 commented May 12, 2026

Summary of Changes

  • Switch SocketcanBus._recv_internal() and send() from select.select() to select.poll().
  • Add regression test test/test_socketcan_high_fd.py (Linux-only) covering send/recv with a mocked socket whose fd is 2048.
  • Add towncrier news fragment.

Related Issues / Pull Requests

Type of Change

  • Bug fix

Checklist

  • I have followed the contribution guide.
  • I have added or updated tests as appropriate.
  • I have added or updated documentation as appropriate.
  • I have added a news fragment for towncrier.
  • All checks and tests pass (tox).

Additional Notes

select.select() is limited by glibc's FD_SETSIZE (1024) and raises ValueError: filedescriptor out of range in select() for higher fds even when the OS limit allows them. select.poll() has no such limit and returns equivalent readiness data. The change is internal to SocketcanBus; the public send/recv signatures and exception semantics are unchanged.

SAY-5 added 3 commits May 11, 2026 21:01
select.select() is limited by glibc's FD_SETSIZE (1024) and raises
ValueError for higher fds even when the OS limit allows them. Switch
SocketcanBus._recv_internal() and send() to select.poll(), which has
no such limit. Fixes hardbyte#2053.

Signed-off-by: SAY-5 <say.apm35@gmail.com>
Signed-off-by: SAY-5 <say.apm35@gmail.com>
@SAY-5 SAY-5 force-pushed the fix/socketcan-high-fd branch from 5d2dca1 to 43dc1a5 Compare May 13, 2026 00:29
while time_left >= 0:
# Wait for write availability
ready = select.select([], [self.socket], [], time_left)[1]
ready = poller.poll(max(0, int(time_left * 1000)))
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the max call for? time_left is alwas positive here.

# being self.socket or an empty list if self.socket is not ready)
ready_receive_sockets, _, _ = select.select([self.socket], [], [], timeout)
# poll() avoids select.select()'s ValueError for fds >= FD_SETSIZE
poller = select.poll()
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You create new poll objects on every read and write. That can't be good for performance.

Create one poll object inside __init__() and register both POLLIN and POLLOUT. Then here you call (fd, event) = self._poller.poll() and check whether the event contains POLLIN.

@@ -0,0 +1,91 @@
#!/usr/bin/env python
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't need to create a new file to test this. Add a test to the existing socketcan tests.

@@ -0,0 +1 @@
``SocketcanBus`` now uses ``select.poll()`` instead of ``select.select()`` so that socket file descriptors above ``FD_SETSIZE`` (1024 on glibc) no longer raise ``ValueError: filedescriptor out of range in select()``.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

SocketcanBus does not support socket file descriptors over 1023

2 participants