From e5afb92cb9454b3e4018f4ccb088a089da2b1228 Mon Sep 17 00:00:00 2001 From: Tristan Schmelcher Date: Fri, 2 Sep 2011 15:29:25 -0700 Subject: [PATCH] Fix race problem with detecting listening inetd sockets The previous detection would fail if the socket closed before we had time to inspect it, which got us stuck in a loop as we would try (and fail) to do accept() on a non-listening socket. --- common/network/TcpSocket.cxx | 18 +++++++----------- common/network/TcpSocket.h | 3 +-- unix/xserver/hw/vnc/vncExtInit.cc | 3 +-- 3 files changed, 9 insertions(+), 15 deletions(-) diff --git a/common/network/TcpSocket.cxx b/common/network/TcpSocket.cxx index 6561f3d6..cf03c10d 100644 --- a/common/network/TcpSocket.cxx +++ b/common/network/TcpSocket.cxx @@ -360,18 +360,14 @@ bool TcpSocket::cork(int sock, bool enable) { #endif } -bool TcpSocket::isSocket(int sock) +bool TcpSocket::isListening(int sock) { - vnc_sockaddr_t sa; - socklen_t sa_size = sizeof(sa); - return getsockname(sock, &sa.u.sa, &sa_size) >= 0; -} - -bool TcpSocket::isConnected(int sock) -{ - vnc_sockaddr_t sa; - socklen_t sa_size = sizeof(sa); - return getpeername(sock, &sa.u.sa, &sa_size) >= 0; + int listening = 0; + socklen_t listening_size = sizeof(listening); + if (getsockopt(sock, SOL_SOCKET, SO_ACCEPTCONN, + (char *)&listening, &listening_size) < 0) + return false; + return listening != 0; } int TcpSocket::getSockPort(int sock) diff --git a/common/network/TcpSocket.h b/common/network/TcpSocket.h index 02f04c91..a97e6839 100644 --- a/common/network/TcpSocket.h +++ b/common/network/TcpSocket.h @@ -65,8 +65,7 @@ namespace network { static bool enableNagles(int sock, bool enable); static bool cork(int sock, bool enable); - static bool isSocket(int sock); - static bool isConnected(int sock); + static bool isListening(int sock); static int getSockPort(int sock); private: bool closeFd; diff --git a/unix/xserver/hw/vnc/vncExtInit.cc b/unix/xserver/hw/vnc/vncExtInit.cc index 2d918b04..863cd36b 100644 --- a/unix/xserver/hw/vnc/vncExtInit.cc +++ b/unix/xserver/hw/vnc/vncExtInit.cc @@ -137,8 +137,7 @@ void vncExtensionInit(void) std::list listeners; std::list httpListeners; if (scr == 0 && vncInetdSock != -1) { - if (network::TcpSocket::isSocket(vncInetdSock) && - !network::TcpSocket::isConnected(vncInetdSock)) + if (network::TcpSocket::isListening(vncInetdSock)) { listeners.push_back(new network::TcpListener(vncInetdSock)); vlog.info("inetd wait"); -- 2.39.5