Make the windows socket handle non inheritable
authorShane Kearns <ext-shane.2.kearns@nokia.com>
Tue, 15 May 2012 14:41:01 +0000 (15:41 +0100)
committerQt by Nokia <qt-info@nokia.com>
Fri, 18 May 2012 09:08:06 +0000 (11:08 +0200)
This is for behaviour consistency with Qt on unix, as well as the
socket close issues described in the task.

Task-number: QTBUG-4465
Change-Id: Ida95650d8a9bd7b5bc3d3926d22e20a6d7eeb30b
Reviewed-by: Robin Burchell <robin+qt@viroteck.net>
Reviewed-by: Joerg Bornemann <joerg.bornemann@nokia.com>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Reviewed-by: Shane Kearns <shane.kearns@accenture.com>
src/network/socket/qnativesocketengine_win.cpp

index bd9550e..db6ace1 100644 (file)
@@ -309,9 +309,18 @@ bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType soc
     int protocol = (socketProtocol == QAbstractSocket::IPv6Protocol
         || (socketProtocol == QAbstractSocket::AnyIPProtocol && QSysInfo::windowsVersion() >= QSysInfo::WV_6_0)) ? AF_INET6 : AF_INET;
     int type = (socketType == QAbstractSocket::UdpSocket) ? SOCK_DGRAM : SOCK_STREAM;
+
     // MSDN KB179942 states that on winnt 4 WSA_FLAG_OVERLAPPED is needed if socket is to be non blocking
     // and recomends alwasy doing it for cross windows version comapablity.
-    SOCKET socket = ::WSASocket(protocol, type, 0, NULL, 0, WSA_FLAG_OVERLAPPED);
+
+    // WSA_FLAG_NO_HANDLE_INHERIT is atomic (like linux O_CLOEXEC), but requires windows 7 SP 1 or later
+    // SetHandleInformation is supported since W2K but isn't atomic
+    // According to the MS docs, we can use the new flag and call GetHandleInformation to see if it was successful
+#ifndef WSA_FLAG_NO_HANDLE_INHERIT
+#define WSA_FLAG_NO_HANDLE_INHERIT 0x80
+#endif
+
+    SOCKET socket = ::WSASocket(protocol, type, 0, NULL, 0, WSA_FLAG_NO_HANDLE_INHERIT | WSA_FLAG_OVERLAPPED);
 
     if (socket == INVALID_SOCKET) {
         int err = WSAGetLastError();
@@ -337,6 +346,19 @@ bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType soc
         return false;
     }
 
+#ifdef HANDLE_FLAG_INHERIT
+    // check if the WSASocket was successful or not at creating a non inheritable socket
+    DWORD handleFlags = 0xFF;
+    if (GetHandleInformation((HANDLE)socket, &handleFlags) && (handleFlags & HANDLE_FLAG_INHERIT)) {
+        // make non inheritable the old way
+        if (SetHandleInformation((HANDLE)socket, HANDLE_FLAG_INHERIT, 0))
+            handleFlags = 0;
+    }
+#ifdef QNATIVESOCKETENGINE_DEBUG
+    qDebug() << "QNativeSocketEnginePrivate::createNewSocket - set inheritable" << handleFlags;
+#endif
+#endif
+
 #if !defined(Q_OS_WINCE)
     if (socketType == QAbstractSocket::UdpSocket) {
         // enable new behavior using