summaryrefslogtreecommitdiff
path: root/win32/win32sck.c
diff options
context:
space:
mode:
authorTomasz Konojacki <me@xenu.pl>2023-03-17 09:24:09 +0100
committerxenu <me@xenu.pl>2023-03-17 09:26:39 +0100
commit8552f09f5cfe61a536a65f11290ef026f7aa0356 (patch)
tree962609984d5e2bb3cd9d1a7ffb168f728e31ebc8 /win32/win32sck.c
parent8a548d15292f2166cb07a69fc5fc943391b7fba5 (diff)
downloadperl-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.c74
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)
{