X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Fsockets.c;h=9d5c54792888eca80025f9123d2c1db7fa4fa52b;hb=fa3486514bd8f15f8eb4c49821d0356b52e5a335;hp=cbec12dbcc4286940f3cf745ea8ce492b13f4bc4;hpb=44608e67a858cbc42b5d6eddd88989e7a1c2d8f9;p=gnulib.git diff --git a/lib/sockets.c b/lib/sockets.c index cbec12dbc..9d5c54792 100644 --- a/lib/sockets.c +++ b/lib/sockets.c @@ -22,9 +22,55 @@ /* Specification. */ #include "sockets.h" +#if WINDOWS_SOCKETS + /* This includes winsock2.h on MinGW. */ #include +#include "close-hook.h" + +/* Get set_winsock_errno, FD_TO_SOCKET etc. */ +#include "w32sock.h" + +static int +close_fd_maybe_socket (int fd, const struct close_hook *remaining_list) +{ + SOCKET sock; + WSANETWORKEVENTS ev; + + /* Test whether fd refers to a socket. */ + sock = FD_TO_SOCKET (fd); + ev.lNetworkEvents = 0xDEADBEEF; + WSAEnumNetworkEvents (sock, NULL, &ev); + if (ev.lNetworkEvents != 0xDEADBEEF) + { + /* fd refers to a socket. */ + /* FIXME: other applications, like squid, use an undocumented + _free_osfhnd free function. But this is not enough: The 'osfile' + flags for fd also needs to be cleared, but it is hard to access it. + Instead, here we just close twice the file descriptor. */ + if (closesocket (sock)) + { + set_winsock_errno (); + return -1; + } + else + { + /* This call frees the file descriptor and does a + CloseHandle ((HANDLE) _get_osfhandle (fd)), which fails. */ + _close (fd); + return 0; + } + } + else + /* Some other type of file descriptor. */ + return execute_close_hooks (fd, remaining_list); +} + +static struct close_hook close_sockets_hook; + +#endif + int gl_sockets_startup (int version) { @@ -38,6 +84,8 @@ gl_sockets_startup (int version) if (data.wVersion < version) return 2; + + register_close_hook (close_fd_maybe_socket, &close_sockets_hook); #endif return 0; @@ -49,6 +97,8 @@ gl_sockets_cleanup (void) #if WINDOWS_SOCKETS int err; + unregister_close_hook (&close_sockets_hook); + err = WSACleanup (); if (err != 0) return 1;