]> source.dussan.org Git - tigervnc.git/commitdiff
Fix race problem with detecting listening inetd sockets
authorTristan Schmelcher <tristan_schmelcher@alumni.uwaterloo.ca>
Fri, 2 Sep 2011 22:29:25 +0000 (15:29 -0700)
committerBrian P. Hinz <bphinz@users.sf.net>
Mon, 4 Jan 2016 02:58:29 +0000 (21:58 -0500)
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
common/network/TcpSocket.h
unix/xserver/hw/vnc/vncExtInit.cc

index 6561f3d64e810ba2307f281ef213dfced44fe3be..cf03c10de7312988fa82d01c6c892ed55e58722a 100644 (file)
@@ -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)
index 02f04c915d0c9a77558eeae9fef6e8dc2bdc05c8..a97e6839d771abff896c165cccb3bc56d5149a25 100644 (file)
@@ -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;
index 2d918b040b4155815049d79a2450154ac34aa28a..863cd36bd993a2999aefcb8445d903fec7a500ea 100644 (file)
@@ -137,8 +137,7 @@ void vncExtensionInit(void)
         std::list<network::TcpListener*> listeners;
         std::list<network::TcpListener*> 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");