summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTristan Schmelcher <tristan_schmelcher@alumni.uwaterloo.ca>2011-09-02 15:29:25 -0700
committerPierre Ossman <ossman@cendio.se>2015-12-29 15:11:26 +0100
commite5afb92cb9454b3e4018f4ccb088a089da2b1228 (patch)
tree808fa899b42e251385d46c9e76d6af0534e362c1
parent1f8aba3147ec13aaa70a44372775b72bb4e59941 (diff)
downloadtigervnc-e5afb92cb9454b3e4018f4ccb088a089da2b1228.tar.gz
tigervnc-e5afb92cb9454b3e4018f4ccb088a089da2b1228.zip
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.
-rw-r--r--common/network/TcpSocket.cxx18
-rw-r--r--common/network/TcpSocket.h3
-rw-r--r--unix/xserver/hw/vnc/vncExtInit.cc3
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<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");