SO_REUSEADDR on Windows is actually akin to SO_REUSEPORT on Linux/BSD. ie it allows 2 apps to listen to the same port at once. Thus we must not set it on Win32 platforms See http://msdn.microsoft.com/en-us/library/windows/desktop/ms740621.aspx Signed-off-by: Daniel P. Berrange <berrange@xxxxxxxxxx> --- src/libvirt_private.syms | 1 + src/rpc/virnetsocket.c | 7 ++----- src/util/virportallocator.c | 4 +--- src/util/virutil.c | 23 +++++++++++++++++++++++ src/util/virutil.h | 1 + 5 files changed, 28 insertions(+), 8 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 5788468..ee2f57b 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2059,6 +2059,7 @@ virSetCloseExec; virSetDeviceUnprivSGIO; virSetInherit; virSetNonBlock; +virSetSockReuseAddr; virSetUIDGID; virSetUIDGIDWithCaps; virStrIsPrint; diff --git a/src/rpc/virnetsocket.c b/src/rpc/virnetsocket.c index 2e94a6c..a7e1783 100644 --- a/src/rpc/virnetsocket.c +++ b/src/rpc/virnetsocket.c @@ -255,8 +255,7 @@ int virNetSocketNewListenTCP(const char *nodename, goto error; } - int opt = 1; - if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) { + if (virSetSockReuseAddr(fd) < 0) { virReportSystemError(errno, "%s", _("Unable to enable port reuse")); goto error; } @@ -460,15 +459,13 @@ int virNetSocketNewConnectTCP(const char *nodename, runp = ai; while (runp) { - int opt = 1; - if ((fd = socket(runp->ai_family, runp->ai_socktype, runp->ai_protocol)) < 0) { virReportSystemError(errno, "%s", _("Unable to create socket")); goto error; } - if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) { + if (virSetSockReuseAddr(fd) < 0) { VIR_WARN("Unable to enable port reuse"); } diff --git a/src/util/virportallocator.c b/src/util/virportallocator.c index ed7bdc2..b68133a 100644 --- a/src/util/virportallocator.c +++ b/src/util/virportallocator.c @@ -116,7 +116,6 @@ static int virPortAllocatorBindToPort(bool *used, struct sockaddr* addr; size_t addrlen; int v6only = 1; - int reuse = 1; int ret = -1; int fd = -1; bool ipv6 = false; @@ -143,8 +142,7 @@ static int virPortAllocatorBindToPort(bool *used, goto cleanup; } - if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void*)&reuse, - sizeof(reuse)) < 0) { + if (virSetSockReuseAddr(fd) < 0) { virReportSystemError(errno, "%s", _("Unable to set socket reuse addr flag")); goto cleanup; diff --git a/src/util/virutil.c b/src/util/virutil.c index 9be1590..65b10b8 100644 --- a/src/util/virutil.c +++ b/src/util/virutil.c @@ -136,6 +136,29 @@ int virSetCloseExec(int fd) return virSetInherit(fd, false); } +#ifdef WIN32 +int virSetSockReuseAddr(int fd ATTRIBUTE_UNUSED) +{ + /* + * SO_REUSEADDR on Windows is actually akin to SO_REUSEPORT + * on Linux/BSD. ie it allows 2 apps to listen to the same + * port at once which is certainly not what we want here. + * + * Win32 sockets have Linux/BSD-like SO_REUSEADDR behaviour + * by default, so we can be a no-op. + * + * http://msdn.microsoft.com/en-us/library/windows/desktop/ms740621.aspx + */ + return 0; +} +#else +int virSetSockReuseAddr(int fd) +{ + int opt = 1; + return setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); +#endif +} + int virPipeReadUntilEOF(int outfd, int errfd, char **outbuf, char **errbuf) { diff --git a/src/util/virutil.h b/src/util/virutil.h index 1f2efd5..2bb74e2 100644 --- a/src/util/virutil.h +++ b/src/util/virutil.h @@ -42,6 +42,7 @@ int virSetBlocking(int fd, bool blocking) ATTRIBUTE_RETURN_CHECK; int virSetNonBlock(int fd) ATTRIBUTE_RETURN_CHECK; int virSetInherit(int fd, bool inherit) ATTRIBUTE_RETURN_CHECK; int virSetCloseExec(int fd) ATTRIBUTE_RETURN_CHECK; +int virSetSockReuseAddr(int fd) ATTRIBUTE_RETURN_CHECK; int virPipeReadUntilEOF(int outfd, int errfd, char **outbuf, char **errbuf); -- 1.9.0 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list