Browse Source

Merge pull request #159 from paullouisageneau/handle-eintr

Handle select interruption
Paul-Louis Ageneau 4 years ago
parent
commit
8f9945b4b9
2 changed files with 32 additions and 26 deletions
  1. 1 1
      deps/libjuice
  2. 31 25
      src/tcptransport.cpp

+ 1 - 1
deps/libjuice

@@ -1 +1 @@
-Subproject commit 5865e915da69db8425c38e3d2403849dfdb22489
+Subproject commit 1cff4dbf1200a3ce3a10cd46a38e3496b4c68e40

+ 31 - 25
src/tcptransport.cpp

@@ -212,36 +212,42 @@ void TcpTransport::connect(const sockaddr *addr, socklen_t addrlen) {
 			throw std::runtime_error(msg.str());
 		}
 
-		fd_set writefds;
-		FD_ZERO(&writefds);
-		FD_SET(mSock, &writefds);
-		struct timeval tv;
-		tv.tv_sec = 10; // TODO
-		tv.tv_usec = 0;
-		ret = ::select(SOCKET_TO_INT(mSock) + 1, NULL, &writefds, NULL, &tv);
-
-		if (ret < 0)
-			throw std::runtime_error("Failed to wait for socket connection");
+		while (true) {
+			fd_set writefds;
+			FD_ZERO(&writefds);
+			FD_SET(mSock, &writefds);
+			struct timeval tv;
+			tv.tv_sec = 10; // TODO: Make the timeout configurable
+			tv.tv_usec = 0;
+			ret = ::select(SOCKET_TO_INT(mSock) + 1, NULL, &writefds, NULL, &tv);
 
-		if (ret == 0) {
-			std::ostringstream msg;
-			msg << "TCP connection to " << node << ":" << serv << " timed out";
-			throw std::runtime_error(msg.str());
-		}
+			if (ret < 0) {
+				if (sockerrno == SEINTR || sockerrno == SEAGAIN) // interrupted
+					continue;
+				else
+					throw std::runtime_error("Failed to wait for socket connection");
+			}
 
-		int error = 0;
-		socklen_t errorlen = sizeof(error);
-		if (::getsockopt(mSock, SOL_SOCKET, SO_ERROR, (char *)&error, &errorlen) != 0)
-			throw std::runtime_error("Failed to get socket error code");
+			if (ret == 0) {
+				std::ostringstream msg;
+				msg << "TCP connection to " << node << ":" << serv << " timed out";
+				throw std::runtime_error(msg.str());
+			}
 
-		if (error != 0) {
-			std::ostringstream msg;
-			msg << "TCP connection to " << node << ":" << serv << " failed, errno=" << error;
-			throw std::runtime_error(msg.str());
-		}
+			int error = 0;
+			socklen_t errorlen = sizeof(error);
+			if (::getsockopt(mSock, SOL_SOCKET, SO_ERROR, (char *)&error, &errorlen) != 0)
+				throw std::runtime_error("Failed to get socket error code");
 
-		PLOG_DEBUG << "TCP connection to " << node << ":" << serv << " succeeded";
+			if (error != 0) {
+				std::ostringstream msg;
+				msg << "TCP connection to " << node << ":" << serv << " failed, errno=" << error;
+				throw std::runtime_error(msg.str());
+			}
 
+			PLOG_DEBUG << "TCP connection to " << node << ":" << serv << " succeeded";
+			break;
+		}
 	} catch (...) {
 		if (mSock != INVALID_SOCKET) {
 			::closesocket(mSock);