Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork33.7k
Description
Bug report
Bug description:
Problem description
We are usingcreate_datagram_endpoint() to set up an asyncio-managed connection to a native hardware CAN bus interface atcan0 under debian linux. We are using thesock named argument to pass in a pre-built raw socket to the FD.
This works in Python 3.5.3 but broke following a migration to 3.11.4. We found that the datagram endpoint would fail to be brought up, and theconnection_made(transport) method on theprotocol_factory would never be called. When I rejigged our code to await the coroutine I got:
ValueError: A UDP Socket was expected, got <socket.socket fd=7, family=29, type=3, proto=1, laddr=('can0',)I believe this has gone unnoticed due to hardware CAN bus interfaces being rare.
Relevant history
Discussion of underlying issues:https://bugs.python.org/issue32331
Core issue
A socket connected to a CAN bus hassock.typesocket.SOCK_RAW, I.E.0b11. This fails the comparison tosocket.SOCK_DGRAM (0b01) socreate_datagram_endpoint() raises an exception because the socket's type fails the "is a datagram" check, even though it is. In 3.5.3 the check was:
(sock.type&socket.SOCK_DGRAM)==socket.SOCK_DGRAM
This worked because it was treating SOCK_DGRAM as a bitwise mask, which it kinda is, but kinda isn't.
x86_64-linux-gnu/bits/socket_type.h:
.../* Types of sockets. */enum__socket_type {SOCK_STREAM=1,/* Sequenced, reliable, connection-based byte streams. */#define SOCK_STREAM SOCK_STREAMSOCK_DGRAM=2,/* Connectionless, unreliable datagrams of fixed maximum length. */#define SOCK_DGRAM SOCK_DGRAMSOCK_RAW=3,/* Raw protocol interface. */#define SOCK_RAW SOCK_RAWSOCK_RDM=4,/* Reliably-delivered messages. */ ...
I am torn on the best way to approach a fix here. I have written a PR that replaces
ifsock.type!=socket.SOCK_DGRAM:
comparisons with
ifnotsock.type&socket.SOCK_DGRAM:
however this perpetuates the enum-vs-bitmask confusion. A more constrained change might be to change
ifsock.type!=socket.SOCK_DGRAM:
to
ifnot (sock.type==socket.SOCK_DGRAM||sock.type==socket.SOCK_RAW):
but that may not catch every instance of the problem. I'd appreciate some guidance on this.
Cheers,
Travis.
CPython versions tested on:
3.11
Operating systems tested on:
Linux
Linked PRs
- gh-114887: Perform bitwise comparisons with SOCK_DGRAM and SOCK_STEAM #114888
- gh-114887 Reject only sockets of type SOCK_STREAM in create_datagram_endpoint(), improve exception message. #114893
- gh-114887 Reject only sockets of type SOCK_STREAM in create_datagram_endpoint(), improve exception message. #114977
- gh-114887 Reject only sockets of type SOCK_STREAM in create_datagram_endpoint(), improve exception message. #114978
- [3.11] gh-114887 Reject only sockets of type SOCK_STREAM in create_da… #114979
- [3.12] gh-114887 Reject only sockets of type SOCK_STREAM in create_da… #114980