Description
With bind(::UDPSocket; reuseaddr=true)
, it's possible to bind the same address multiple times, with only the last bind receiving any traffic. On macOS, that fails for specific addresses, such as 0.0.0.0
. This does not cause any errors (I expected -EADDRINUSE
) while causing subsequent recv
s to hang.
MWE:
using Sockets
const ip = IPv4("0.0.0.0")
let sock = UDPSocket()
bind(sock, ip, 12345; reuseaddr=true)
println("Waiting...")
@show data = recv(sock)
println("Received ", Base.format_bytes(length(data)))
end
println()
let sock = UDPSocket()
bind(sock, ip, 12345; reuseaddr=true)
println("Waiting...")
@show data = recv(sock)
println("Received ", Base.format_bytes(length(data)))
end
Meanwhile, in a different terminal, run echo -n test | nc -u 127.0.0.1 12345
or so twice. On macOS, this will result in the second recv
call never returning, while on Linux everything works fine.
I haven't looked in the platform specifics of SO_REUSEADDR/SO_REUSEPORT yet -- it seems like quite a mess -- so this may be a platform limitation (as the libuv docs suggest). However, if possible I think we should detect an impossible reuseaddr
request and throw an error. If that's not possible, at the very least the docs should warn about it.
Changing the address to 127.0.0.1 works around the issue.