You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
uvloop does not support original unix udp socketpair #304
raiseRuntimeError("cannot convert sockaddr into Python object")
@ZhuYuJin 's code fails because __convert_sockaddr_to_pyaddr doesn't support AF_UNSPEC. @1st1 shall we patch __convert_sockaddr_to_pyaddr so that it returns an empty string if the family is AF_UNSPEC like this (Solution A)?
staticPyObject*makesockaddr(SOCKET_Tsockfd, structsockaddr*addr, size_taddrlen, intproto)
{
if (addrlen==0) {
/* No address -- may be recvfrom() from known socket */Py_RETURN_NONE;
}
Guess solution D would be to update __convert_sockaddr_to_pyaddr to include this logic.
And I don't think it is a reliable way to check if the first byte is \0 as an equivalent to checking addrlen == 0 in __convert_sockaddr_to_pyaddr, because we don't know for sure what addr->sa_family is.
In this case, I would go for solution B if no objections.
By the way, @ZhuYuJin 's code doesn't work with vanilla asyncio - it uses sendto if peername is not set:
Bad news: libuv didn't provide the addrlen (the msg_namelen below as a value-result argument) for callbacks (I'll file an issue in libuv):
I think I also encountered this limitation myself one time, so resolving this at the libuv level would be great. IIRC I also had problems with dealing with abstract unix sockets in libuv, and maybe it was somehow related to this, I don't remember now.
Activity
fantix commentedon Apr 4, 2020
This seems to be a low-level behavior:
And
((struct sockaddr_un *) &peer)->sun_pathis always an empty string.Related code:
uvloop/uvloop/handles/udp.pyx
Line 335 in 2870219
uvloop/uvloop/dns.pyx
Lines 64 to 68 in 2870219
@ZhuYuJin 's code fails because
__convert_sockaddr_to_pyaddrdoesn't supportAF_UNSPEC. @1st1 shall we patch__convert_sockaddr_to_pyaddrso that it returns an empty string if the family isAF_UNSPEClike this (Solution A)?Alternatively, we could patch
udp.pyxto handle it like this (Solution B):Or less efficiently but support potential future changes to
__convert_sockaddr_to_pyaddr(Solution C):ZhuYuJin commentedon Apr 17, 2020
@fantix It should solve the problem.
However, I specify a unix socket pair. Why does it become a AF_UNSPEC?
This code performs well in Mac OS.
fantix commentedon Apr 17, 2020
Yeah, I think it is from Linux kernel - I tried to track it down but it's a lot of code to read, so we might want to work it around in uvloop first.
1st1 commentedon Apr 17, 2020
C or B would work. How does CPython deal with this btw?
fantix commentedon Apr 17, 2020
That's a really good point - let me check.
fantix commentedon Apr 17, 2020
Looks like it'll just return
None:https://github.com/python/cpython/blob/87502ddd710eb1f030b8ff5a60b05becea3f474f/Modules/socketmodule.c#L1335-L1341
Guess solution D would be to update
__convert_sockaddr_to_pyaddrto include this logic.1st1 commentedon Apr 22, 2020
Yep!
fantix commentedon Apr 25, 2020
Bad news: libuv didn't provide the
addrlen(themsg_namelenbelow as a value-result argument) for callbacks (I'll file an issue in libuv):https://github.com/libuv/libuv/blob/16910d23a34b8b8c313d24824fd85383aa8a8d40/src/unix/udp.c#L180-L200
And I don't think it is a reliable way to check if the first byte is
\0as an equivalent to checkingaddrlen == 0in__convert_sockaddr_to_pyaddr, because we don't know for sure whataddr->sa_familyis.In this case, I would go for solution B if no objections.
By the way, @ZhuYuJin 's code doesn't work with vanilla asyncio - it uses
sendtoifpeernameis not set:https://github.com/python/cpython/blob/515fce4fc4bb0d2db97b17df275cf90640017f56/Lib/asyncio/selector_events.py#L1043-L1046
But the
peernameis always empty for asocketpair:Should we consider this a bug in CPython asyncio and fix it there too?
1st1 commentedon Apr 26, 2020
Yeah, let's to B.
I think I also encountered this limitation myself one time, so resolving this at the libuv level would be great. IIRC I also had problems with dealing with abstract unix sockets in libuv, and maybe it was somehow related to this, I don't remember now.
Accept empty addr in UDP on_receive
Accept empty addr in UDP on_receive
Accept empty addr in UDP on_receive
Accept empty addr in UDP on_receive