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)
This commit is contained in:
committed by
Eli Zaretskii
parent
8b31d850e1
commit
dda6201a97
34
src/w32.c
34
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,
|
||||
|
||||
Reference in New Issue
Block a user