summaryrefslogtreecommitdiffstats
path: root/gl/sockets.c
diff options
context:
space:
mode:
Diffstat (limited to 'gl/sockets.c')
-rw-r--r--gl/sockets.c50
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
35static int 36static int
36close_fd_maybe_socket (int fd, const struct close_hook *remaining_list) 37close_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
70static struct close_hook close_sockets_hook; 77static int
78ioctl_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
105static struct fd_hook fd_sockets_hook;
71 106
72static int initialized_sockets_version /* = 0 */; 107static 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)