@@ -237,11 +237,7 @@ void uv_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle) {
237237 handle -> reqs_pending == 0 ) {
238238 assert (!(handle -> flags & UV_HANDLE_CLOSED ));
239239
240- if (!(handle -> flags & UV_HANDLE_TCP_SOCKET_CLOSED )) {
241- closesocket (handle -> socket );
242- handle -> socket = INVALID_SOCKET ;
243- handle -> flags |= UV_HANDLE_TCP_SOCKET_CLOSED ;
244- }
240+ assert (handle -> flags & UV_HANDLE_TCP_SOCKET_CLOSED );
245241
246242 if (!(handle -> flags & UV_HANDLE_CONNECTION ) && handle -> tcp .serv .accept_reqs ) {
247243 if (handle -> flags & UV_HANDLE_EMULATE_IOCP ) {
@@ -769,7 +765,7 @@ static int uv__is_loopback(const struct sockaddr_storage* storage) {
769765}
770766
771767// Check if Windows version is 10.0.16299 or later
772- static int uv__is_fast_loopback_fail_supported () {
768+ static int uv__is_fast_loopback_fail_supported (void ) {
773769 OSVERSIONINFOW os_info ;
774770 if (!pRtlGetVersion )
775771 return 0 ;
@@ -1402,13 +1398,16 @@ int uv_tcp_simultaneous_accepts(uv_tcp_t* handle, int enable) {
14021398}
14031399
14041400
1405- static int uv_tcp_try_cancel_io (uv_tcp_t * tcp ) {
1406- SOCKET socket = tcp -> socket ;
1401+ static void uv_tcp_try_cancel_read (uv_tcp_t * tcp ) {
1402+ SOCKET socket ;
14071403 int non_ifs_lsp ;
14081404
1405+ CancelIoEx ((HANDLE ) tcp -> socket , & tcp -> read_req .u .io .overlapped );
1406+
14091407 /* Check if we have any non-IFS LSPs stacked on top of TCP */
14101408 non_ifs_lsp = (tcp -> flags & UV_HANDLE_IPV6 ) ? uv_tcp_non_ifs_lsp_ipv6 :
14111409 uv_tcp_non_ifs_lsp_ipv4 ;
1410+ socket = tcp -> socket ;
14121411
14131412 /* If there are non-ifs LSPs then try to obtain a base handle for the socket.
14141413 * This will always fail on Windows XP/3k. */
@@ -1424,83 +1423,44 @@ static int uv_tcp_try_cancel_io(uv_tcp_t* tcp) {
14241423 NULL ,
14251424 NULL ) != 0 ) {
14261425 /* Failed. We can't do CancelIo. */
1427- return -1 ;
1426+ return ;
14281427 }
14291428 }
14301429
14311430 assert (socket != 0 && socket != INVALID_SOCKET );
14321431
1433- if (! CancelIo (( HANDLE ) socket ) ) {
1434- return GetLastError ( );
1432+ if (socket != tcp -> socket ) {
1433+ CancelIoEx (( HANDLE ) socket , & tcp -> read_req . u . io . overlapped );
14351434 }
1436-
1437- /* It worked. */
1438- return 0 ;
14391435}
14401436
14411437
14421438void uv_tcp_close (uv_loop_t * loop , uv_tcp_t * tcp ) {
1443- int close_socket = 1 ;
1444-
1445- if (tcp -> flags & UV_HANDLE_READ_PENDING ) {
1446- /* In order for winsock to do a graceful close there must not be any any
1447- * pending reads, or the socket must be shut down for writing */
1448- if (!(tcp -> flags & UV_HANDLE_SHARED_TCP_SOCKET )) {
1449- /* Just do shutdown on non-shared sockets, which ensures graceful close. */
1450- shutdown (tcp -> socket , SD_SEND );
1451-
1452- } else if (uv_tcp_try_cancel_io (tcp ) == 0 ) {
1453- /* In case of a shared socket, we try to cancel all outstanding I/O,. If
1454- * that works, don't close the socket yet - wait for the read req to
1455- * return and close the socket in uv_tcp_endgame. */
1456- close_socket = 0 ;
1457-
1458- } else {
1459- /* When cancelling isn't possible - which could happen when an LSP is
1460- * present on an old Windows version, we will have to close the socket
1461- * with a read pending. That is not nice because trailing sent bytes may
1462- * not make it to the other side. */
1463- }
1464-
1465- } else if ((tcp -> flags & UV_HANDLE_SHARED_TCP_SOCKET ) &&
1466- tcp -> tcp .serv .accept_reqs != NULL ) {
1467- /* Under normal circumstances closesocket() will ensure that all pending
1468- * accept reqs are canceled. However, when the socket is shared the
1469- * presence of another reference to the socket in another process will keep
1470- * the accept reqs going, so we have to ensure that these are canceled. */
1471- if (uv_tcp_try_cancel_io (tcp ) != 0 ) {
1472- /* When cancellation is not possible, there is another option: we can
1473- * close the incoming sockets, which will also cancel the accept
1474- * operations. However this is not cool because we might inadvertently
1475- * close a socket that just accepted a new connection, which will cause
1476- * the connection to be aborted. */
1477- unsigned int i ;
1478- for (i = 0 ; i < uv_simultaneous_server_accepts ; i ++ ) {
1479- uv_tcp_accept_t * req = & tcp -> tcp .serv .accept_reqs [i ];
1480- if (req -> accept_socket != INVALID_SOCKET &&
1481- !HasOverlappedIoCompleted (& req -> u .io .overlapped )) {
1482- closesocket (req -> accept_socket );
1483- req -> accept_socket = INVALID_SOCKET ;
1484- }
1439+ if (tcp -> tcp .serv .accept_reqs != NULL ) {
1440+ /* First close the incoming sockets to cancel the accept operations before
1441+ * we free their resources. */
1442+ unsigned int i ;
1443+ for (i = 0 ; i < uv_simultaneous_server_accepts ; i ++ ) {
1444+ uv_tcp_accept_t * req = & tcp -> tcp .serv .accept_reqs [i ];
1445+ if (req -> accept_socket != INVALID_SOCKET ) {
1446+ closesocket (req -> accept_socket );
1447+ req -> accept_socket = INVALID_SOCKET ;
14851448 }
14861449 }
14871450 }
14881451
14891452 if (tcp -> flags & UV_HANDLE_READING ) {
1490- tcp -> flags &= ~ UV_HANDLE_READING ;
1491- DECREASE_ACTIVE_COUNT ( loop , tcp );
1453+ uv_tcp_try_cancel_read ( tcp ) ;
1454+ uv_read_stop (( uv_stream_t * ) tcp );
14921455 }
1493-
14941456 if (tcp -> flags & UV_HANDLE_LISTENING ) {
14951457 tcp -> flags &= ~UV_HANDLE_LISTENING ;
14961458 DECREASE_ACTIVE_COUNT (loop , tcp );
14971459 }
14981460
1499- if (close_socket ) {
1500- closesocket (tcp -> socket );
1501- tcp -> socket = INVALID_SOCKET ;
1502- tcp -> flags |= UV_HANDLE_TCP_SOCKET_CLOSED ;
1503- }
1461+ closesocket (tcp -> socket );
1462+ tcp -> socket = INVALID_SOCKET ;
1463+ tcp -> flags |= UV_HANDLE_TCP_SOCKET_CLOSED ;
15041464
15051465 tcp -> flags &= ~(UV_HANDLE_READABLE | UV_HANDLE_WRITABLE );
15061466 uv__handle_closing (tcp );
0 commit comments