change socket / file descriptor checks on windows
based on discussion in https://github.com/libressl/portable/issues/266 and https://bugs.python.org/issue23524 adjust the compat layer for Windows to use _get_osfhandle in combination with _set_thread_local_invalid_parameter_handler if applicable to more reliably determine if a handle is a socket, file, or closed socket. This prevents assertions when calling tls_close on an already-closed socket.
This commit is contained in:
parent
4aa7642130
commit
afcd4be8a7
@ -121,7 +121,7 @@ if(WIN32)
|
|||||||
if(NOT CMAKE_SYSTEM_NAME MATCHES "WindowsStore")
|
if(NOT CMAKE_SYSTEM_NAME MATCHES "WindowsStore")
|
||||||
add_definitions(-D_WIN32_WINNT=0x0600)
|
add_definitions(-D_WIN32_WINNT=0x0600)
|
||||||
endif()
|
endif()
|
||||||
set(PLATFORM_LIBS ${PLATFORM_LIBS} ws2_32 bcrypt)
|
set(PLATFORM_LIBS ${PLATFORM_LIBS} ws2_32 ntdll bcrypt)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(MSVC)
|
if(MSVC)
|
||||||
|
@ -148,6 +148,61 @@ wsa_errno(int err)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Employ a similar trick to cpython (pycore_fileutils.h) where the CRT report
|
||||||
|
* handler is disabled while checking if a descriptor is a socket or a file
|
||||||
|
*/
|
||||||
|
#if defined _MSC_VER && _MSC_VER >= 1900
|
||||||
|
|
||||||
|
#include <crtdbg.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
typedef void (*_invalid_parameter_handler)(
|
||||||
|
const wchar_t * expression,
|
||||||
|
const wchar_t * function,
|
||||||
|
const wchar_t * file,
|
||||||
|
unsigned int line,
|
||||||
|
uintptr_t pReserved
|
||||||
|
);
|
||||||
|
|
||||||
|
extern _invalid_parameter_handler _set_thread_local_invalid_parameter_handler(
|
||||||
|
_invalid_parameter_handler pNew
|
||||||
|
);
|
||||||
|
|
||||||
|
static void noop_handler(const wchar_t *expression, const wchar_t *function,
|
||||||
|
const wchar_t *file, unsigned int line, uintptr_t pReserved)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define BEGIN_SUPPRESS_IPH \
|
||||||
|
_invalid_parameter_handler old_handler = _set_thread_local_invalid_parameter_handler(noop_handler)
|
||||||
|
#define END_SUPPRESS_IPH \
|
||||||
|
_set_thread_local_invalid_parameter_handler(old_handler)
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define BEGIN_SUPPRESS_IPH
|
||||||
|
#define END_SUPPRESS_IPH
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int
|
||||||
|
is_socket(int fd)
|
||||||
|
{
|
||||||
|
intptr_t hd;
|
||||||
|
|
||||||
|
BEGIN_SUPPRESS_IPH;
|
||||||
|
hd = _get_osfhandle(fd);
|
||||||
|
END_SUPPRESS_IPH;
|
||||||
|
|
||||||
|
if (hd == (intptr_t)INVALID_HANDLE_VALUE) {
|
||||||
|
return 1; /* fd is not file descriptor */
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
posix_connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
|
posix_connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
|
||||||
{
|
{
|
||||||
@ -160,24 +215,31 @@ posix_connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
|
|||||||
int
|
int
|
||||||
posix_close(int fd)
|
posix_close(int fd)
|
||||||
{
|
{
|
||||||
if (closesocket(fd) == SOCKET_ERROR) {
|
int rc;
|
||||||
int err = WSAGetLastError();
|
|
||||||
return (err == WSAENOTSOCK || err == WSAEBADF ||
|
if (is_socket(fd)) {
|
||||||
err == WSANOTINITIALISED) ?
|
if ((rc = closesocket(fd)) == SOCKET_ERROR) {
|
||||||
close(fd) : wsa_errno(err);
|
int err = WSAGetLastError();
|
||||||
|
rc = wsa_errno(err);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rc = close(fd);
|
||||||
}
|
}
|
||||||
return 0;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t
|
ssize_t
|
||||||
posix_read(int fd, void *buf, size_t count)
|
posix_read(int fd, void *buf, size_t count)
|
||||||
{
|
{
|
||||||
ssize_t rc = recv(fd, buf, count, 0);
|
ssize_t rc;
|
||||||
if (rc == SOCKET_ERROR) {
|
|
||||||
int err = WSAGetLastError();
|
if (is_socket(fd)) {
|
||||||
return (err == WSAENOTSOCK || err == WSAEBADF ||
|
if ((rc = recv(fd, buf, count, 0)) == SOCKET_ERROR) {
|
||||||
err == WSANOTINITIALISED) ?
|
int err = WSAGetLastError();
|
||||||
read(fd, buf, count) : wsa_errno(err);
|
rc = wsa_errno(err);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rc = read(fd, buf, count);
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@ -185,12 +247,13 @@ posix_read(int fd, void *buf, size_t count)
|
|||||||
ssize_t
|
ssize_t
|
||||||
posix_write(int fd, const void *buf, size_t count)
|
posix_write(int fd, const void *buf, size_t count)
|
||||||
{
|
{
|
||||||
ssize_t rc = send(fd, buf, count, 0);
|
ssize_t rc;
|
||||||
if (rc == SOCKET_ERROR) {
|
if (is_socket(fd)) {
|
||||||
int err = WSAGetLastError();
|
if ((rc = send(fd, buf, count, 0)) == SOCKET_ERROR) {
|
||||||
return (err == WSAENOTSOCK || err == WSAEBADF ||
|
rc = wsa_errno(WSAGetLastError());
|
||||||
err == WSANOTINITIALISED) ?
|
}
|
||||||
write(fd, buf, count) : wsa_errno(err);
|
} else {
|
||||||
|
rc = write(fd, buf, count);
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@ -199,17 +262,32 @@ int
|
|||||||
posix_getsockopt(int sockfd, int level, int optname,
|
posix_getsockopt(int sockfd, int level, int optname,
|
||||||
void *optval, socklen_t *optlen)
|
void *optval, socklen_t *optlen)
|
||||||
{
|
{
|
||||||
int rc = getsockopt(sockfd, level, optname, (char *)optval, optlen);
|
int rc;
|
||||||
return rc == 0 ? 0 : wsa_errno(WSAGetLastError());
|
if (is_socket(sockfd)) {
|
||||||
|
rc = getsockopt(sockfd, level, optname, (char *)optval, optlen);
|
||||||
|
if (rc == 0) {
|
||||||
|
rc = wsa_errno(WSAGetLastError());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rc = -1;
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
posix_setsockopt(int sockfd, int level, int optname,
|
posix_setsockopt(int sockfd, int level, int optname,
|
||||||
const void *optval, socklen_t optlen)
|
const void *optval, socklen_t optlen)
|
||||||
{
|
{
|
||||||
int rc = setsockopt(sockfd, level, optname, (char *)optval, optlen);
|
int rc;
|
||||||
return rc == 0 ? 0 : wsa_errno(WSAGetLastError());
|
if (is_socket(sockfd)) {
|
||||||
|
rc = setsockopt(sockfd, level, optname, (char *)optval, optlen);
|
||||||
|
if (rc == 0) {
|
||||||
|
rc = wsa_errno(WSAGetLastError());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rc = -1;
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
uid_t getuid(void)
|
uid_t getuid(void)
|
||||||
@ -241,5 +319,4 @@ int gettimeofday(struct timeval * tp, struct timezone * tzp)
|
|||||||
tp->tv_usec = (long)(system_time.wMilliseconds * 1000);
|
tp->tv_usec = (long)(system_time.wMilliseconds * 1000);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user