diff options
author | Tomasz Konojacki <me@xenu.pl> | 2023-03-17 09:24:09 +0100 |
---|---|---|
committer | xenu <me@xenu.pl> | 2023-03-17 09:26:39 +0100 |
commit | 8552f09f5cfe61a536a65f11290ef026f7aa0356 (patch) | |
tree | 962609984d5e2bb3cd9d1a7ffb168f728e31ebc8 /win32/win32sck.c | |
parent | 8a548d15292f2166cb07a69fc5fc943391b7fba5 (diff) | |
download | perl-8552f09f5cfe61a536a65f11290ef026f7aa0356.tar.gz |
win32: inject a socket-aware version of CloseHandle() into the CRT
_close() on an fd calls CloseHandle(), which is illegal if the fd
contains a socket handle.
We previously worked around this by having our own close(), which called
closesocket() before calling _close()
(e601c439adce167078ac7b49550c0418ace86f94).
Amusingly, the author of that solution thought it's just a temporary
workaround:
/*
* close RTL fd while respecting sockets
* added as temporary measure until PerlIO has real
* Win32 native layer
* -- BKS, 11-11-2000
*/
To make it thread-safe, we had to manipulate the internals of file
descriptors, which kept changing
(b47a847f6284f6f98ad7509cf77a4aeb802d8fce).
Unfortunately, the C runtime has been rewritten and it no longer exposes
them at all. We had to disable the thread-safety fix in Visual C++ 2015
builds (1f664ef5314fb6e438137c44c95cf5ecdbdb5e9b). It also wouldn't work
with MinGW configured to use UCRT.
This commit introduces a new solution: we inject a socket-aware version
of CloseHandle() into the C runtime library. Hopefully, this will be
less fragile.
This also fixes a few issues that the original solution didn't:
- Closing a busy pipe doesn't cause a deadlock (fixes #19963)
- _dup2 properly closes an overwritten socket (fixes #20920)
Diffstat (limited to 'win32/win32sck.c')
-rw-r--r-- | win32/win32sck.c | 74 |
1 files changed, 0 insertions, 74 deletions
diff --git a/win32/win32sck.c b/win32/win32sck.c index f08b7bea29..4edd1407a4 100644 --- a/win32/win32sck.c +++ b/win32/win32sck.c @@ -632,80 +632,6 @@ win32_socket(int af, int type, int protocol) return s; } -/* - * close RTL fd while respecting sockets - * added as temporary measure until PerlIO has real - * Win32 native layer - * -- BKS, 11-11-2000 -*/ - -int my_close(int fd) -{ - int osf; - osf = TO_SOCKET(fd);/* Get it now before it's gone! */ - if (osf != -1) { - int err; - err = closesocket(osf); - if (err == 0) { -#ifdef _set_osfhnd - assert(_osfhnd(fd) == osf); /* catch a bad ioinfo struct def */ - /* don't close freed handle */ - _set_osfhnd(fd, INVALID_HANDLE_VALUE); - return close(fd); -#else - (void)close(fd); /* handle already closed, ignore error */ - return 0; -#endif - } - else if (err == SOCKET_ERROR) { - int wsaerr = WSAGetLastError(); - err = convert_wsa_error_to_errno(wsaerr); - if (err != ENOTSOCK) { - (void)close(fd); - errno = err; - SetLastError(wsaerr); - return EOF; - } - } - } - return close(fd); -} - -#undef fclose -int -my_fclose (FILE *pf) -{ - int osf; - osf = TO_SOCKET(win32_fileno(pf));/* Get it now before it's gone! */ - if (osf != -1) { - int err; - win32_fflush(pf); - err = closesocket(osf); - if (err == 0) { -#ifdef _set_osfhnd - assert(_osfhnd(win32_fileno(pf)) == osf); /* catch a bad ioinfo struct def */ - /* don't close freed handle */ - _set_osfhnd(win32_fileno(pf), INVALID_HANDLE_VALUE); - return fclose(pf); -#else - (void)fclose(pf); /* handle already closed, ignore error */ - return 0; -#endif - } - else if (err == SOCKET_ERROR) { - int wsaerr = WSAGetLastError(); - err = convert_wsa_error_to_errno(wsaerr); - if (err != ENOTSOCK) { - (void)fclose(pf); - errno = err; - SetLastError(wsaerr); - return EOF; - } - } - } - return fclose(pf); -} - struct hostent * win32_gethostbyaddr(const char *addr, int len, int type) { |