Skip to content

Commit 328ae63

Browse files
committed
unix-ffi/socket: Use C socket type directly instead of Python subclass.
MicroPython's stream protocol inheritance is broken for Python subclasses of C types: the C-level MP_STREAM_GET_FILENO ioctl reads from the wrong object layout, returning a garbage fd. This causes select.poll / asyncio to poll the wrong descriptor. Remove the socket subclass and use _socket.socket directly, moving accept's address translation to a standalone helper. Made-with: Cursor
1 parent f794795 commit 328ae63

1 file changed

Lines changed: 16 additions & 21 deletions

File tree

unix-ffi/socket/socket.py

Lines changed: 16 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -27,33 +27,28 @@ def inet_aton(addr):
2727
return inet_pton(AF_INET, addr)
2828

2929

30+
# Do NOT subclass _socket.socket in Python: MicroPython's stream protocol
31+
# inheritance is broken for Python subclasses of C types -- the C-level
32+
# MP_STREAM_GET_FILENO ioctl reads from the mp_obj_instance_t layout
33+
# (members map) instead of the mp_obj_socket_t layout, returning a garbage
34+
# fd value. This causes select.poll / asyncio to poll the wrong fd.
35+
# Use the C type directly and provide helpers as standalone functions.
36+
socket = _socket.socket
37+
38+
39+
def _wrap_accept(sock):
40+
"""Accept a connection, returning (new_socket, (ip_str, port))."""
41+
s, addr = sock.accept()
42+
addr = _socket.sockaddr(addr)
43+
return (s, (_socket.inet_ntop(addr[0], addr[1]), addr[2]))
44+
45+
3046
def create_connection(addr, timeout=None, source_address=None):
3147
s = socket()
32-
# print("Address:", addr)
3348
ais = getaddrinfo(addr[0], addr[1])
34-
# print("Address infos:", ais)
3549
for ai in ais:
3650
try:
3751
s.connect(ai[4])
3852
return s
3953
except:
4054
pass
41-
42-
43-
class socket(_socket.socket):
44-
def accept(self):
45-
s, addr = super().accept()
46-
addr = _socket.sockaddr(addr)
47-
return (s, (_socket.inet_ntop(addr[0], addr[1]), addr[2]))
48-
49-
def bind(self, addr):
50-
return super().bind(_resolve_addr(addr))
51-
52-
def connect(self, addr):
53-
return super().connect(_resolve_addr(addr))
54-
55-
def sendall(self, *args):
56-
return self.send(*args)
57-
58-
def sendto(self, data, addr):
59-
return super().sendto(data, _resolve_addr(addr))

0 commit comments

Comments
 (0)