[WSD] Fix socket duplication to allow the parent application to close
authorftillier <ftillier@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Tue, 10 Jan 2006 19:49:14 +0000 (19:49 +0000)
committerftillier <ftillier@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Tue, 10 Jan 2006 19:49:14 +0000 (19:49 +0000)
its socket before the child has completed duplication.

git-svn-id: svn://openib.tc.cornell.edu/gen1/trunk@213 ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86

ulp/wsd/user/ibsp_duplicate.c
ulp/wsd/user/ibsp_iblow.c
ulp/wsd/user/ibspdebug.h
ulp/wsd/user/ibspdll.c
ulp/wsd/user/ibspproto.h
ulp/wsd/user/ibspstruct.h

index 46fd724..1838054 100644 (file)
@@ -41,9 +41,15 @@ static void
 create_name(\r
                OUT                     char                                            *fname,\r
        IN              const   DWORD                                           dwProcessId,\r
-       IN              const   DWORD                                           identifier )\r
+       IN              const   GUID                                            *p_guid )\r
 {\r
-       sprintf( fname, "SilverStorm-WSD-%08lx-%08lx", dwProcessId, identifier );\r
+       sprintf( fname, "Global\\OpenIB-WSD-%08lx-"\r
+               "%08lx-%04hx-%04hx-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x",\r
+               dwProcessId, p_guid->Data1, p_guid->Data2, p_guid->Data3,\r
+               (int)p_guid->Data4[0], (int)p_guid->Data4[1],\r
+               (int)p_guid->Data4[2], (int)p_guid->Data4[3],\r
+               (int)p_guid->Data4[4], (int)p_guid->Data4[5],\r
+               (int)p_guid->Data4[6], (int)p_guid->Data4[7] );\r
 }\r
 \r
 \r
@@ -53,53 +59,19 @@ create_name(
 int\r
 setup_duplicate_socket(\r
        IN                              struct ibsp_socket_info         *socket_info,\r
-       IN                              DWORD                                           identifier )\r
+       IN                              HANDLE                                          h_dup_info )\r
 {\r
-       char fname[100];\r
-       HANDLE h = NULL;\r
        int ret, err;\r
        struct ibsp_duplicate_info *dup_info;\r
        ib_net64_t dest_port_guid;\r
        ib_path_rec_t path_rec;\r
 \r
-       IBSP_ENTER( IBSP_DBG_CONN );\r
+       IBSP_ENTER( IBSP_DBG_DUP );\r
 \r
        CL_ASSERT( socket_info->socket_state == IBSP_CREATE );\r
 \r
-       fzprint(("%s():%d:0x%x:0x%x: socket=0x%p dwProcessId=0x%x\n", __FUNCTION__,\r
-                        __LINE__, GetCurrentProcessId(), GetCurrentThreadId(), socket_info));\r
-\r
-\r
-       /* Find the info created and shared by the previous controlling socket. */\r
-       create_name( fname, GetCurrentProcessId(), identifier );\r
-\r
-       h = CreateFileMapping( INVALID_HANDLE_VALUE,    // use paging file\r
-                                                 NULL, // default security attributes\r
-                                                 PAGE_READWRITE,       // read access\r
-                                                 0,    // size: high 32-bits\r
-                                                 sizeof(struct ibsp_duplicate_info),   // size: low 32-bits\r
-                                                 fname );      // name of map object\r
-       if( h == NULL )\r
-       {\r
-               IBSP_ERROR( ("CreateFileMapping failed with %d\n", GetLastError()) );\r
-               ret = WSAENETDOWN;\r
-               goto err1;\r
-       }\r
-\r
-       /* Make sure this file already existed. */\r
-       if( GetLastError() != ERROR_ALREADY_EXISTS )\r
-       {\r
-               IBSP_ERROR( ("not mapping for socket duplicate info\n") );\r
-               ret = WSAENETDOWN;\r
-               goto err1;\r
-       }\r
-\r
        /* Get a pointer to the file-mapped shared memory. */\r
-       dup_info = MapViewOfFile( h,    // object to map view of\r
-                                                        FILE_MAP_WRITE,        // read/write access\r
-                                                        0,     // high offset:  map from\r
-                                                        0,     // low offset:   beginning\r
-                                                        0 );   // default: map entire file\r
+       dup_info = MapViewOfFile( h_dup_info, FILE_MAP_READ, 0, 0, 0 );\r
        if( dup_info == NULL )\r
        {\r
                IBSP_ERROR( ("MapViewOfFile failed with %d\n", GetLastError()) );\r
@@ -111,10 +83,8 @@ setup_duplicate_socket(
        socket_info->local_addr = dup_info->local_addr;\r
        socket_info->socket_options = dup_info->socket_options;\r
        socket_info->duplicate.dwProcessId = dup_info->dwProcessId;\r
-       socket_info->duplicate.identifier = identifier;\r
+       socket_info->duplicate.identifier = dup_info->identifier;\r
 \r
-       /* Get the port info */\r
-       /* Find the destination IP address */\r
        socket_info->port = get_port_from_ip_address( dup_info->local_addr.sin_addr );\r
        if( socket_info->port == NULL )\r
        {\r
@@ -192,143 +162,153 @@ err2:
        }\r
 \r
 err1:\r
-       if( h )\r
-               CloseHandle( h );\r
-\r
        if( socket_info->h_event )\r
        {\r
                CloseHandle( socket_info->h_event );\r
                socket_info->h_event = NULL;\r
        }\r
 \r
-       IBSP_EXIT( IBSP_DBG_CONN );\r
+       CloseHandle( h_dup_info );\r
+\r
+       IBSP_EXIT( IBSP_DBG_DUP );\r
        return ret;\r
 }\r
 \r
 \r
-/*\r
- * This function is called by the previous controlling process.\r
- * Called with the socket_info->mutex held.\r
- */\r
-int\r
-prepare_duplicate_socket(\r
-       IN                              struct ibsp_socket_info         *socket_info,\r
-       IN                              DWORD                                           dwProcessId )\r
+/* Function: IBSPDuplicateSocket\r
+\r
+ Description:\r
+    This function provides a WSAPROTOCOL_INFOW structure which can be passed\r
+    to another process to open a handle to the same socket. First we need\r
+    to translate the user socket into the provider socket and call the underlying\r
+    WSPDuplicateSocket. Note that the lpProtocolInfo structure passed into us\r
+    is an out parameter only!\r
+*/\r
+int WSPAPI\r
+IBSPDuplicateSocket(\r
+                                       SOCKET                                          s,\r
+                                       DWORD                                           dwProcessId,\r
+                                       LPWSAPROTOCOL_INFOW                     lpProtocolInfo,\r
+                                       LPINT                                           lpErrno )\r
 {\r
+       struct ibsp_socket_info *socket_info = (struct ibsp_socket_info *)s;\r
        struct ibsp_duplicate_info *dup_info = NULL;\r
-       int i;\r
-       DWORD identifier = 0;\r
+       char fname[100];\r
+       GUID guid;\r
+       HANDLE h_dup_info, h_target_process, h_target_dup_info;\r
        struct disconnect_reason reason;\r
 \r
-       IBSP_ENTER( IBSP_DBG_CONN );\r
+       IBSP_ENTER( IBSP_DBG_DUP );\r
 \r
-       fzprint(("%s():%d:0x%x:0x%x: socket=0x%p dwProcessId=0x%x \n", __FUNCTION__,\r
-                        __LINE__, GetCurrentProcessId(),\r
-                        GetCurrentThreadId(), socket_info, dwProcessId));\r
+       IBSP_TRACE4( IBSP_DBG_DUP,\r
+               ("Duplicating socket=0x%p to dwProcessId=0x%x \n",\r
+               socket_info, dwProcessId) );\r
+\r
+       cl_spinlock_acquire( &socket_info->mutex );\r
+       if( socket_info->socket_state != IBSP_CONNECTED )\r
+       {\r
+               cl_spinlock_release( &socket_info->mutex );\r
+               IBSP_TRACE_EXIT( IBSP_DBG_DUP,\r
+                       ("Socket state not IBSP_CONNECTED, state=%s.\n",\r
+                       IBSP_SOCKET_STATE_STR( socket_info->socket_state )) );\r
+               *lpErrno = WSAENOTCONN;\r
+               return SOCKET_ERROR;\r
+       }\r
 \r
-       /* First, flush all the receive buffers. There should be no send/rdma buffers left. */\r
-       CL_ASSERT( socket_info->socket_state == IBSP_CONNECTED );\r
        IBSP_CHANGE_SOCKET_STATE( socket_info, IBSP_DUPLICATING_OLD );\r
 \r
        /* We changed the state - remove from connection map. */\r
        ibsp_conn_remove( socket_info );\r
 \r
-       /* We might have a left-over from the previous duplicate. */\r
-       if( socket_info->duplicate.mmap_handle != NULL )\r
+       cl_spinlock_release( &socket_info->mutex );\r
+\r
+       /* Create a GUID to use as unique identifier for this duplication. */\r
+       UuidCreate( &guid );\r
+       create_name( fname, dwProcessId, &guid );\r
+\r
+       h_dup_info = CreateFileMapping( INVALID_HANDLE_VALUE, NULL,\r
+               PAGE_READWRITE, 0, sizeof(struct ibsp_duplicate_info), fname );\r
+       if( !h_dup_info )\r
        {\r
-               CloseHandle( socket_info->duplicate.mmap_handle );\r
-               socket_info->duplicate.mmap_handle = NULL;\r
+               IBSP_ERROR_EXIT(\r
+                       ("CreateFileMapping for %s failed with %d\n",\r
+                       fname, GetLastError()) );\r
+               *lpErrno = WSAENETDOWN;\r
+               return SOCKET_ERROR;\r
+       }\r
+\r
+       /* Get a pointer to the file-mapped shared memory. */\r
+       dup_info = MapViewOfFile( h_dup_info, FILE_MAP_WRITE, 0, 0, 0 );\r
+       if( !dup_info )\r
+       {\r
+               IBSP_ERROR_EXIT(\r
+                       ("MapViewOfFile failed with %d\n", GetLastError()) );\r
+               CloseHandle( h_dup_info );\r
+               *lpErrno = WSAENETDOWN;\r
+               return SOCKET_ERROR;\r
        }\r
 \r
        /* \r
-        * Share this socket_info so the next-controlling process can get the necessary\r
-        * information to create the duplicated socket. Ensure a unique identifier. \r
+        * Store addressing information so that the duplicating\r
+        * process can reconnect.\r
         */\r
-       for( i = 0; i < 50; i++ )\r
+       dup_info->identifier = guid;\r
+       dup_info->socket_options = socket_info->socket_options;\r
+       dup_info->peer_addr = socket_info->peer_addr;\r
+       dup_info->local_addr = socket_info->local_addr;\r
+       dup_info->dwProcessId = dwProcessId;\r
+\r
+       /* Release the reference on the underlying file */\r
+       UnmapViewOfFile( dup_info );\r
+\r
+       /* Open the target process. */\r
+       h_target_process = OpenProcess( PROCESS_DUP_HANDLE, FALSE, dwProcessId );\r
+       if( !h_target_process )\r
        {\r
-               char fname[100];\r
-               GUID guid;\r
-\r
-               /* Create a GUID and collapse it into 32 bits. */\r
-               UuidCreate( &guid );\r
-               identifier = guid.Data1 ^ (guid.Data2 << 16 | guid.Data3) ^\r
-                       (guid.Data4[7] << 24 | guid.Data4[6] << 16 | guid.Data4[5] << 8 | guid.\r
-                        Data4[4]) ^ (guid.Data4[3] << 24 | guid.Data4[2] << 16 | guid.\r
-                                                 Data4[1] << 8 | guid.Data4[0]);\r
-\r
-               create_name( fname, dwProcessId, identifier );\r
-\r
-               socket_info->duplicate.mmap_handle = CreateFileMapping( INVALID_HANDLE_VALUE,   // use paging file\r
-                                                                                                                          NULL,        // default security attributes\r
-                                                                                                                          PAGE_READWRITE,      // read access\r
-                                                                                                                          0,   // size: high 32-bits\r
-                                                                                                                          sizeof(struct ibsp_duplicate_info),  // size: low 32-bits\r
-                                                                                                                          fname );     // name of map object\r
-\r
-               if( socket_info->duplicate.mmap_handle == NULL )\r
-               {\r
-                       IBSP_ERROR_EXIT(\r
-                               ("CreateFileMapping failed with %d\n", GetLastError()) );\r
-                       return WSAENETDOWN;\r
-               }\r
-\r
-               /* Make sure this identifier is unique for that process.  */\r
-               if( GetLastError() == ERROR_ALREADY_EXISTS )\r
-               {\r
-                       CloseHandle( socket_info->duplicate.mmap_handle );\r
-                       socket_info->duplicate.mmap_handle = NULL;\r
-\r
-                       /* Try again. */\r
-                       continue;\r
-               }\r
-\r
-               /* Get a pointer to the file-mapped shared memory. */\r
-               dup_info = MapViewOfFile( socket_info->duplicate.mmap_handle,   // object to map view of\r
-                                                                FILE_MAP_WRITE,        // read/write access\r
-                                                                0,     // high offset:  map from\r
-                                                                0,     // low offset:   beginning\r
-                                                                0 );   // default: map entire file\r
-               if( dup_info == NULL )\r
-               {\r
-                       IBSP_ERROR_EXIT(\r
-                               ("MapViewOfFile failed with %d\n", GetLastError()) );\r
-                       CloseHandle( socket_info->duplicate.mmap_handle );\r
-                       socket_info->duplicate.mmap_handle = NULL;\r
-                       return WSAENETDOWN;\r
-               }\r
+               IBSP_ERROR_EXIT(\r
+                       ("OpenProcess failed with %d\n", GetLastError()) );\r
+               CloseHandle( h_dup_info );\r
+               *lpErrno = WSAENETDOWN;\r
+               return SOCKET_ERROR;\r
        }\r
 \r
-       if( dup_info == NULL )\r
+       if( !DuplicateHandle( GetCurrentProcess(), h_dup_info,\r
+               h_target_process, &h_target_dup_info, 0, TRUE,\r
+               DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS ) )\r
        {\r
-               IBSP_ERROR_EXIT( ("failed to get a unique identifier\n") );\r
-               CloseHandle( socket_info->duplicate.mmap_handle );\r
-               socket_info->duplicate.mmap_handle = NULL;\r
-               return WSAENETDOWN;\r
+               IBSP_ERROR_EXIT(\r
+                       ("DuplicateHandle failed with %d\n", GetLastError()) );\r
+               CloseHandle( h_target_process );\r
+               *lpErrno = WSAENETDOWN;\r
+               return SOCKET_ERROR;\r
        }\r
 \r
-       socket_info->duplicate.identifier = identifier;\r
+       CloseHandle( h_target_process );\r
+\r
+       CL_ASSERT( !((ULONG_PTR)h_target_dup_info >> 32) );\r
+       lpProtocolInfo->dwProviderReserved = (DWORD)(ULONG_PTR)h_target_dup_info;\r
+\r
+       socket_info->duplicate.identifier = guid;\r
 \r
        memset( &reason, 0, sizeof(reason) );\r
        reason.type = DISC_DUPLICATING;\r
-       reason.duplicating.identifier = identifier;\r
+       reason.duplicating.identifier = guid;\r
        reason.duplicating.dwProcessId = dwProcessId;\r
 \r
-       cl_spinlock_release( &socket_info->mutex );\r
+       /*\r
+        * Flush all the receive buffers. There should be no\r
+        * send/rdma buffers left.\r
+        */\r
        ib_disconnect( socket_info, &reason );\r
 \r
        wait_cq_drain( socket_info );\r
 \r
        cl_spinlock_acquire( &socket_info->mutex );\r
        ib_destroy_socket( socket_info );\r
-\r
-       /* Put enough info in dup_info so that the remote socket can recreate the connection. */\r
-       dup_info->port_guid = socket_info->port->guid;\r
-       dup_info->socket_options = socket_info->socket_options;\r
-       dup_info->peer_addr = socket_info->peer_addr;\r
-       dup_info->local_addr = socket_info->local_addr;\r
-       dup_info->dwProcessId = dwProcessId;\r
+       cl_spinlock_release( &socket_info->mutex );\r
 \r
        /* And that's it */\r
-       IBSP_EXIT( IBSP_DBG_CONN );\r
+       IBSP_EXIT( IBSP_DBG_DUP );\r
+       *lpErrno = 0;\r
        return 0;\r
 }\r
index 0122fbe..87c318e 100644 (file)
@@ -1098,12 +1098,6 @@ shutdown_and_destroy_socket_info(
        IBSP_CHANGE_SOCKET_STATE( socket_info, IBSP_CLOSED );\r
        cl_spinlock_release( &socket_info->mutex );\r
 \r
-       if( socket_info->duplicate.mmap_handle )\r
-       {\r
-               CloseHandle( socket_info->duplicate.mmap_handle );\r
-               socket_info->duplicate.mmap_handle = NULL;\r
-       }\r
-\r
        if( socket_info->listen.handle )\r
        {\r
                /* Stop listening and reject queued connections. */\r
index 3a9f84e..5fed257 100644 (file)
@@ -48,6 +48,7 @@ extern uint32_t gdbg_lvl;
 #define IBSP_DBG_NEV           0x00000400      /* network events */\r
 #define IBSP_DBG_HW                    0x00000800      /* Hardware */\r
 #define IBSP_DBG_IO                    0x00001000      /* Overlapped I/O request */\r
+#define IBSP_DBG_DUP           0x00002000      /* Socket Duplication */\r
 \r
 #define IBSP_DBG_LEVEL4                0x01000000      /* debug use */\r
 #define IBSP_DBG_LEVEL3                0x02000000      /* debug use */\r
index 1c372a7..177b735 100644 (file)
@@ -825,61 +825,6 @@ done:
 }\r
 \r
 \r
-/* Function: IBSPDuplicateSocket\r
-\r
- Description:\r
-    This function provides a WSAPROTOCOL_INFOW structure which can be passed\r
-    to another process to open a handle to the same socket. First we need\r
-    to translate the user socket into the provider socket and call the underlying\r
-    WSPDuplicateSocket. Note that the lpProtocolInfo structure passed into us\r
-    is an out parameter only!\r
-*/\r
-static int WSPAPI\r
-IBSPDuplicateSocket(\r
-                                       SOCKET                                          s,\r
-                                       DWORD                                           dwProcessId,\r
-                                       LPWSAPROTOCOL_INFOW                     lpProtocolInfo,\r
-                                       LPINT                                           lpErrno )\r
-{\r
-       struct ibsp_socket_info *socket_info = (struct ibsp_socket_info *)s;\r
-       int ret;\r
-\r
-       IBSP_ENTER( IBSP_DBG_CONN );\r
-\r
-       fzprint(("%s():%d:0x%x:0x%x: socket=0x%p state=%s\n", __FUNCTION__,\r
-                        __LINE__, GetCurrentProcessId(),\r
-                        GetCurrentThreadId(), s, IBSP_SOCKET_STATE_STR( socket_info->socket_state )));\r
-\r
-       cl_spinlock_acquire( &socket_info->mutex );\r
-       if( socket_info->socket_state != IBSP_CONNECTED )\r
-       {\r
-               cl_spinlock_release( &socket_info->mutex );\r
-               IBSP_TRACE_EXIT( IBSP_DBG_CONN,\r
-                       ("Socket state not IBSP_CONNECTED, state=%s.\n",\r
-                       IBSP_SOCKET_STATE_STR( socket_info->socket_state )) );\r
-               *lpErrno = WSAENOTCONN;\r
-               return SOCKET_ERROR;\r
-       }\r
-\r
-       ret = prepare_duplicate_socket( socket_info, dwProcessId );\r
-       cl_spinlock_release( &socket_info->mutex );\r
-       if( ret )\r
-       {\r
-               IBSP_TRACE_EXIT( IBSP_DBG_CONN,\r
-                       ("prepare_duplicate_socket failed with %d\n", ret) );\r
-               *lpErrno = ret;\r
-               return SOCKET_ERROR;\r
-       }\r
-       else\r
-       {\r
-               IBSP_EXIT( IBSP_DBG_CONN );\r
-               lpProtocolInfo->dwProviderReserved = socket_info->duplicate.identifier;\r
-               *lpErrno = 0;\r
-               return 0;\r
-       }\r
-}\r
-\r
-\r
 /* Function: IBSPEnumNetworkEvents\r
  * \r
  *  Description:\r
@@ -1431,7 +1376,8 @@ IBSPListen(
                IBSP_CHANGE_SOCKET_STATE( socket_info, IBSP_LISTEN );\r
 \r
                socket_info->listen.listen_req_param.dwProcessId = 0;\r
-               socket_info->listen.listen_req_param.identifier = 0;\r
+               cl_memclr( &socket_info->listen.listen_req_param.identifier,\r
+                       sizeof(socket_info->listen.listen_req_param.identifier) );\r
 \r
                ret = ib_listen( socket_info );\r
                if( ret )\r
@@ -2089,8 +2035,8 @@ IBSPSocket(
        if( lpProtocolInfo->dwProviderReserved != 0 )\r
        {\r
                /* This is a duplicate socket. */\r
-               *lpErrno = setup_duplicate_socket(\r
-                       socket_info, lpProtocolInfo->dwProviderReserved );\r
+               *lpErrno = setup_duplicate_socket( socket_info,\r
+                       (HANDLE)(ULONG_PTR)lpProtocolInfo->dwProviderReserved );\r
                if( *lpErrno )\r
                {\r
                        deref_socket_info( socket_info );\r
index 4f866f8..98ad7ea 100644 (file)
@@ -227,12 +227,14 @@ pnp_ca_remove(
 int\r
 setup_duplicate_socket(\r
        IN                              struct ibsp_socket_info         *socket_info,\r
-       IN                              DWORD                                           identifier );\r
+       IN                              HANDLE                                          h_dup_info );\r
 \r
-int\r
-prepare_duplicate_socket(\r
-       IN                              struct ibsp_socket_info         *socket_info,\r
-       IN                              DWORD                                           dwProcessId );\r
+int WSPAPI\r
+IBSPDuplicateSocket(\r
+                                       SOCKET                                          s,\r
+                                       DWORD                                           dwProcessId,\r
+                                       LPWSAPROTOCOL_INFOW                     lpProtocolInfo,\r
+                                       LPINT                                           lpErrno );\r
 \r
 /* ibsp_mem.c */\r
 \r
index fe04c40..4d152f2 100644 (file)
@@ -73,7 +73,7 @@ struct ibsp_socket_options
 struct listen_req_param\r
 {\r
        DWORD dwProcessId;\r
-       DWORD identifier;\r
+       GUID identifier;\r
 };\r
 \r
 /* Parameters given to establish a connection */\r
@@ -125,7 +125,7 @@ struct mr_list
 /* Information necessary to duplicate sockets */\r
 struct ibsp_duplicate_info\r
 {\r
-       ib_net64_t port_guid;\r
+       GUID identifier;\r
        struct ibsp_socket_options socket_options;\r
        struct sockaddr_in local_addr;\r
        struct sockaddr_in peer_addr;\r
@@ -144,7 +144,7 @@ struct disconnect_reason
 \r
        struct _disconnect_reason_dup\r
        {\r
-               DWORD identifier;\r
+               GUID identifier;\r
                DWORD dwProcessId;\r
 \r
        }       duplicating;\r
@@ -316,8 +316,7 @@ struct ibsp_socket_info
        /* Stuff for socket duplication */\r
        struct\r
        {\r
-               HANDLE mmap_handle;\r
-               DWORD identifier;               /* Unique identifier */\r
+               GUID identifier;                /* Unique identifier */\r
                DWORD dwProcessId;\r
        } duplicate;\r
 \r