From dda6201a972a344c3cf2f35e61511f2cd62670f2 Mon Sep 17 00:00:00 2001 From: Alain Schneble Date: Thu, 10 Mar 2016 16:43:09 +0200 Subject: [PATCH] Fix asynchronous TLS connections on MS-Windows * src/w32.c (sys_write): Don't switch the socket to blocking mode if the connection attempt is in progress. Instead, return either EWOULDBLOCK immediately if the connection is in progress, or the error code produced by '_sys_wait_connect' if the connection failed. Switching the socket to blocking mode was found to interfere with GnuTLS handshake. (Bug#22789) --- src/w32.c | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/src/w32.c b/src/w32.c index ccf7cc335ce..c55315275c7 100644 --- a/src/w32.c +++ b/src/w32.c @@ -8772,6 +8772,30 @@ sys_write (int fd, const void * buffer, unsigned int count) unsigned long nblock = 0; if (winsock_lib == NULL) emacs_abort (); + child_process *cp = fd_info[fd].cp; + + /* If this is a non-blocking socket whose connection is in + progress or terminated with an error already, return the + proper error code to the caller. */ + if (cp != NULL && (fd_info[fd].flags & FILE_CONNECT) != 0) + { + /* In case connection is in progress, ENOTCONN that would + result from calling pfn_send is not what callers expect. */ + if (cp->status != STATUS_CONNECT_FAILED) + { + errno = EWOULDBLOCK; + return -1; + } + /* In case connection failed, use the actual error code + stashed by '_sys_wait_connect' in cp->errcode. */ + else if (cp->errcode != 0) + { + pfn_WSASetLastError (cp->errcode); + set_errno (); + return -1; + } + } + /* TODO: implement select() properly so non-blocking I/O works. */ /* For now, make sure the write blocks. */ if (fd_info[fd].flags & FILE_NDELAY) @@ -8782,14 +8806,8 @@ sys_write (int fd, const void * buffer, unsigned int count) if (nchars == SOCKET_ERROR) { set_errno (); - /* If this is a non-blocking socket whose connection is in - progress, return the proper error code to the caller; - ENOTCONN is not what they expect . */ - if (errno == ENOTCONN && (fd_info[fd].flags & FILE_CONNECT) != 0) - errno = EWOULDBLOCK; - else - DebPrint (("sys_write.send failed with error %d on socket %ld\n", - pfn_WSAGetLastError (), SOCK_HANDLE (fd))); + DebPrint (("sys_write.send failed with error %d on socket %ld\n", + pfn_WSAGetLastError (), SOCK_HANDLE (fd))); } /* Set the socket back to non-blocking if it was before, -- 2.39.2