X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Fsockets.c;h=b946c7e63deca8440e6816abe4000cddeea381bc;hb=fb0f15d4d3057fd142dcd3d6d86b26ba719a88c2;hp=658119ea43252ae98f9a4cedd8f0eee7929092fa;hpb=bb2bf54fe80c58cf9ed9cb71447743060970d198;p=gnulib.git diff --git a/lib/sockets.c b/lib/sockets.c index 658119ea4..b946c7e63 100644 --- a/lib/sockets.c +++ b/lib/sockets.c @@ -1,6 +1,6 @@ /* sockets.c --- wrappers for Windows socket functions - Copyright (C) 2008 Free Software Foundation, Inc. + Copyright (C) 2008-2010 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -19,24 +19,81 @@ #include +/* Specification. */ +#include "sockets.h" + +#if WINDOWS_SOCKETS + /* This includes winsock2.h on MinGW. */ -#include +# include -#include "sockets.h" +# 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; + +static int initialized_sockets_version /* = 0 */; + +#endif /* WINDOWS_SOCKETS */ int -gl_sockets_startup (int version) +gl_sockets_startup (int version _GL_UNUSED) { #if WINDOWS_SOCKETS - WSADATA data; - int err; + if (version > initialized_sockets_version) + { + WSADATA data; + int err; - err = WSAStartup (version, &data); - if (err != 0) - return 1; + err = WSAStartup (version, &data); + if (err != 0) + return 1; + + if (data.wVersion < version) + return 2; + + if (initialized_sockets_version == 0) + register_close_hook (close_fd_maybe_socket, &close_sockets_hook); - if (data.wVersion < version) - return 2; + initialized_sockets_version = version; + } #endif return 0; @@ -48,6 +105,10 @@ gl_sockets_cleanup (void) #if WINDOWS_SOCKETS int err; + initialized_sockets_version = 0; + + unregister_close_hook (&close_sockets_hook); + err = WSACleanup (); if (err != 0) return 1;