I have a multithreaded Linux server with many simultaneous connections (2 connections per thread) which must bind to a public IP address when responding to a client. From time to time, I get a EADDRINUSE
error when binding a UDP socket, even though my logs indicate that the last time a socket was bound to the same address/port AND called shutdown()
and close()
on the socket was 30 minutes before.
Moreover, I set SO_REUSEADDR
, SO_REUSEPORT
and IP_TRANSPARENT
on these UDP sockets (but not ones that are automatically bound to a local address/port). With these options, even if there were some other UDP socket still bound to the same port on a local address, binding should not fail as per SO_REUSEADDR
, but it clearly does happen.
I can find no explanation for this behaviour.
int makeUDPSocket(sockaddr_in *bindTo)
{
int sock;
if(-1 == (sock = socket(AF_INET, SOCK_DGRAM | SOCK_NONBLOCK, 0)))
{
log("Could not make client UDP socket! Exiting.");
exit(18);
}
if(bindTo)
{
int enable = 1;
if (-1 == setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char*)&enable, sizeof(enable)))
{
log("Could not set SO_REUSEADDR on UDP socket; errno=" + std::to_string(errno));
exit(2);
}
if (-1 == setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, (const char*)&enable, sizeof(enable)))
{
log("Could not set SO_REUSEPORT on UDP socket; errno=" + std::to_string(errno));
exit(2);
}
if(-1 == setsockopt(sock, SOL_IP, IP_TRANSPARENT, (const char*)&enable, sizeof(enable)))
{
log("Could not set IP_TRANSPARENT on UDP socket; errno=" + std::to_string(errno));
exit(2);
}
if(-1 == bind(sock, (sockaddr*)bindTo, sizeof(sockaddr_in)))
{
log("Could not bind UDP socket. errno=" + std::to_string(errno) + ". Exiting.");
exit(19);
}
}
return sock;
}
void myfunc()
{
int sock0 = makeUDPSocket(NULL);
int sock1 = makeUDPSocket(&myPubAddr);
doStuff(sock0, sock1);
shutdown(sock0, SHUT_RDWR);
close(sock0);
shutdown(sock1, SHUT_RDWR);
close(sock1);
}