diff options
Diffstat (limited to 'gl/sockets.c')
-rw-r--r-- | gl/sockets.c | 50 |
1 files changed, 43 insertions, 7 deletions
diff --git a/gl/sockets.c b/gl/sockets.c index b946c7e..ae96148 100644 --- a/gl/sockets.c +++ b/gl/sockets.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* sockets.c --- wrappers for Windows socket functions | 1 | /* sockets.c --- wrappers for Windows socket functions |
2 | 2 | ||
3 | Copyright (C) 2008-2010 Free Software Foundation, Inc. | 3 | Copyright (C) 2008-2013 Free Software Foundation, Inc. |
4 | 4 | ||
5 | This program is free software: you can redistribute it and/or modify | 5 | This program is free software: you can redistribute it and/or modify |
6 | it under the terms of the GNU General Public License as published by | 6 | it under the terms of the GNU General Public License as published by |
@@ -27,14 +27,21 @@ | |||
27 | /* This includes winsock2.h on MinGW. */ | 27 | /* This includes winsock2.h on MinGW. */ |
28 | # include <sys/socket.h> | 28 | # include <sys/socket.h> |
29 | 29 | ||
30 | # include "close-hook.h" | 30 | # include "fd-hook.h" |
31 | # include "msvc-nothrow.h" | ||
31 | 32 | ||
32 | /* Get set_winsock_errno, FD_TO_SOCKET etc. */ | 33 | /* Get set_winsock_errno, FD_TO_SOCKET etc. */ |
33 | # include "w32sock.h" | 34 | # include "w32sock.h" |
34 | 35 | ||
35 | static int | 36 | static int |
36 | close_fd_maybe_socket (int fd, const struct close_hook *remaining_list) | 37 | close_fd_maybe_socket (const struct fd_hook *remaining_list, |
38 | gl_close_fn primary, | ||
39 | int fd) | ||
37 | { | 40 | { |
41 | /* Note about multithread-safety: There is a race condition where, between | ||
42 | our calls to closesocket() and the primary close(), some other thread | ||
43 | could make system calls that allocate precisely the same HANDLE value | ||
44 | as sock; then the primary close() would call CloseHandle() on it. */ | ||
38 | SOCKET sock; | 45 | SOCKET sock; |
39 | WSANETWORKEVENTS ev; | 46 | WSANETWORKEVENTS ev; |
40 | 47 | ||
@@ -64,10 +71,38 @@ close_fd_maybe_socket (int fd, const struct close_hook *remaining_list) | |||
64 | } | 71 | } |
65 | else | 72 | else |
66 | /* Some other type of file descriptor. */ | 73 | /* Some other type of file descriptor. */ |
67 | return execute_close_hooks (fd, remaining_list); | 74 | return execute_close_hooks (remaining_list, primary, fd); |
68 | } | 75 | } |
69 | 76 | ||
70 | static struct close_hook close_sockets_hook; | 77 | static int |
78 | ioctl_fd_maybe_socket (const struct fd_hook *remaining_list, | ||
79 | gl_ioctl_fn primary, | ||
80 | int fd, int request, void *arg) | ||
81 | { | ||
82 | SOCKET sock; | ||
83 | WSANETWORKEVENTS ev; | ||
84 | |||
85 | /* Test whether fd refers to a socket. */ | ||
86 | sock = FD_TO_SOCKET (fd); | ||
87 | ev.lNetworkEvents = 0xDEADBEEF; | ||
88 | WSAEnumNetworkEvents (sock, NULL, &ev); | ||
89 | if (ev.lNetworkEvents != 0xDEADBEEF) | ||
90 | { | ||
91 | /* fd refers to a socket. */ | ||
92 | if (ioctlsocket (sock, request, arg) < 0) | ||
93 | { | ||
94 | set_winsock_errno (); | ||
95 | return -1; | ||
96 | } | ||
97 | else | ||
98 | return 0; | ||
99 | } | ||
100 | else | ||
101 | /* Some other type of file descriptor. */ | ||
102 | return execute_ioctl_hooks (remaining_list, primary, fd, request, arg); | ||
103 | } | ||
104 | |||
105 | static struct fd_hook fd_sockets_hook; | ||
71 | 106 | ||
72 | static int initialized_sockets_version /* = 0 */; | 107 | static int initialized_sockets_version /* = 0 */; |
73 | 108 | ||
@@ -90,7 +125,8 @@ gl_sockets_startup (int version _GL_UNUSED) | |||
90 | return 2; | 125 | return 2; |
91 | 126 | ||
92 | if (initialized_sockets_version == 0) | 127 | if (initialized_sockets_version == 0) |
93 | register_close_hook (close_fd_maybe_socket, &close_sockets_hook); | 128 | register_fd_hook (close_fd_maybe_socket, ioctl_fd_maybe_socket, |
129 | &fd_sockets_hook); | ||
94 | 130 | ||
95 | initialized_sockets_version = version; | 131 | initialized_sockets_version = version; |
96 | } | 132 | } |
@@ -107,7 +143,7 @@ gl_sockets_cleanup (void) | |||
107 | 143 | ||
108 | initialized_sockets_version = 0; | 144 | initialized_sockets_version = 0; |
109 | 145 | ||
110 | unregister_close_hook (&close_sockets_hook); | 146 | unregister_fd_hook (&fd_sockets_hook); |
111 | 147 | ||
112 | err = WSACleanup (); | 148 | err = WSACleanup (); |
113 | if (err != 0) | 149 | if (err != 0) |