Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--winsup/cygwin/fhandler.cc2
-rw-r--r--winsup/cygwin/fhandler.h194
-rw-r--r--winsup/cygwin/fhandler_socket.cc559
-rw-r--r--winsup/cygwin/fhandler_socket_inet.cc607
-rw-r--r--winsup/cygwin/fhandler_socket_local.cc427
-rw-r--r--winsup/cygwin/net.cc3
-rw-r--r--winsup/cygwin/poll.cc6
-rw-r--r--winsup/cygwin/select.cc70
8 files changed, 711 insertions, 1157 deletions
diff --git a/winsup/cygwin/fhandler.cc b/winsup/cygwin/fhandler.cc
index 086be7311..93bbdfed2 100644
--- a/winsup/cygwin/fhandler.cc
+++ b/winsup/cygwin/fhandler.cc
@@ -1567,7 +1567,7 @@ fhandler_base::fork_fixup (HANDLE parent, HANDLE &h, const char *name)
{
HANDLE oh = h;
bool res = false;
- if (/* !is_socket () && */ !close_on_exec ())
+ if (!close_on_exec ())
debug_printf ("handle %p already opened", h);
else if (!DuplicateHandle (parent, h, GetCurrentProcess (), &h,
0, !close_on_exec (), DUPLICATE_SAME_ACCESS))
diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index 4c7fea3e3..3816110a0 100644
--- a/winsup/cygwin/fhandler.h
+++ b/winsup/cygwin/fhandler.h
@@ -406,6 +406,7 @@ public:
virtual bool isfifo () const { return false; }
virtual int ptsname_r (char *, size_t);
virtual class fhandler_socket *is_socket () { return NULL; }
+ virtual class fhandler_socket_wsock *is_wsock_socket () { return NULL; }
virtual class fhandler_console *is_console () { return 0; }
virtual int is_windows () {return 0; }
@@ -488,7 +489,6 @@ class fhandler_socket: public fhandler_base
protected:
int addr_family;
int type;
- virtual int af_local_connect () = 0;
inline int get_socket_flags ()
{
int ret = 0;
@@ -500,18 +500,6 @@ class fhandler_socket: public fhandler_base
}
protected:
- wsa_event *wsock_events;
- HANDLE wsock_mtx;
- HANDLE wsock_evt;
- bool init_events ();
- int wait_for_events (const long event_mask, const DWORD flags);
- void release_events ();
- public:
- const HANDLE wsock_event () const { return wsock_evt; }
- int evaluate_events (const long event_mask, long &events, const bool erase);
- const LONG serial_number () const { return wsock_events->serial_number; }
-
- protected:
int _rmem;
int _wmem;
public:
@@ -528,55 +516,29 @@ class fhandler_socket: public fhandler_base
DWORD &sndtimeo () { return _sndtimeo; }
protected:
- struct _WSAPROTOCOL_INFOW *prot_info_ptr;
-
- protected:
struct status_flags
{
unsigned async_io : 1; /* async I/O */
unsigned saw_shutdown_read : 1; /* Socket saw a SHUT_RD */
unsigned saw_shutdown_write : 1; /* Socket saw a SHUT_WR */
- unsigned saw_reuseaddr : 1; /* Socket saw SO_REUSEADDR call */
unsigned connect_state : 3;
- unsigned no_getpeereid : 1;
public:
status_flags () :
async_io (0), saw_shutdown_read (0), saw_shutdown_write (0),
- connect_state (unconnected), no_getpeereid (0)
+ connect_state (unconnected)
{}
} status;
-
-#ifdef __INSIDE_CYGWIN_NET__
- int set_socket_handle (SOCKET sock, int af, int type, int flags);
-#endif
-
public:
- fhandler_socket ();
- ~fhandler_socket ();
-/* Originally get_socket returned an int, which is not a good idea
- to cast a handle to on 64 bit. The right type here is very certainly
- SOCKET instead. On the other hand, we don't want to have to include
- winsock.h just to build fhandler.h. Therefore we define get_socket
- now only when building network related code. */
-#ifdef __INSIDE_CYGWIN_NET__
- SOCKET get_socket () { return (SOCKET) get_handle(); }
-#endif
- fhandler_socket *is_socket () { return this; }
-
IMPLEMENT_STATUS_FLAG (bool, async_io)
IMPLEMENT_STATUS_FLAG (bool, saw_shutdown_read)
IMPLEMENT_STATUS_FLAG (bool, saw_shutdown_write)
- IMPLEMENT_STATUS_FLAG (bool, saw_reuseaddr)
IMPLEMENT_STATUS_FLAG (conn_state, connect_state)
- IMPLEMENT_STATUS_FLAG (bool, no_getpeereid)
- bool need_fixup_before () const {return prot_info_ptr != NULL;}
- void set_close_on_exec (bool val);
- void init_fixup_before ();
- int fixup_before_fork_exec (DWORD);
- void fixup_after_fork (HANDLE);
- void fixup_after_exec ();
- int dup (fhandler_base *child, int);
+ public:
+ fhandler_socket ();
+ ~fhandler_socket ();
+ fhandler_socket *is_socket () { return this; }
+
char *get_proc_fd_name (char *buf);
virtual int socket (int af, int type, int protocol, int flags) = 0;
@@ -633,14 +595,96 @@ class fhandler_socket: public fhandler_base
virtual select_record *select_except (select_stuff *) = 0;
};
-class fhandler_socket_inet: public fhandler_socket
+/* Encapsulate wsock-based socket classes fhandler_socket_inet and
+ fhandler_socket_local during development of fhandler_socket_unix.
+ TODO: Perhaps we should keep it that way, under the assumption that
+ the Windows 10 AF_UNIX class will eventually get useful at one point. */
+class fhandler_socket_wsock: public fhandler_socket
+{
+ protected:
+ virtual int af_local_connect () = 0;
+
+ protected:
+ wsa_event *wsock_events;
+ HANDLE wsock_mtx;
+ HANDLE wsock_evt;
+ bool init_events ();
+ int wait_for_events (const long event_mask, const DWORD flags);
+ void release_events ();
+ public:
+ const HANDLE wsock_event () const { return wsock_evt; }
+ int evaluate_events (const long event_mask, long &events, const bool erase);
+ const LONG serial_number () const { return wsock_events->serial_number; }
+
+ protected:
+ struct _WSAPROTOCOL_INFOW *prot_info_ptr;
+ public:
+ bool need_fixup_before () const {return prot_info_ptr != NULL;}
+ void set_close_on_exec (bool val);
+ void init_fixup_before ();
+ int fixup_before_fork_exec (DWORD);
+ void fixup_after_fork (HANDLE);
+ void fixup_after_exec ();
+ int dup (fhandler_base *child, int);
+
+#ifdef __INSIDE_CYGWIN_NET__
+ protected:
+ int set_socket_handle (SOCKET sock, int af, int type, int flags);
+ public:
+ /* Originally get_socket returned an int, which is not a good idea
+ to cast a handle to on 64 bit. The right type here is very certainly
+ SOCKET instead. On the other hand, we don't want to have to include
+ winsock.h just to build fhandler.h. Therefore we define get_socket
+ now only when building network related code. */
+ SOCKET get_socket () { return (SOCKET) get_handle(); }
+#endif
+
+ protected:
+ struct status_flags
+ {
+ unsigned saw_reuseaddr : 1; /* Socket saw SO_REUSEADDR call */
+ public:
+ status_flags () : saw_reuseaddr (0) {}
+ } status;
+ public:
+ IMPLEMENT_STATUS_FLAG (bool, saw_reuseaddr)
+
+ protected:
+ virtual ssize_t recv_internal (struct _WSAMSG *wsamsg, bool use_recvmsg) = 0;
+ ssize_t send_internal (struct _WSAMSG *wsamsg, int flags);
+
+ public:
+ fhandler_socket_wsock ();
+ ~fhandler_socket_wsock ();
+
+ fhandler_socket_wsock *is_wsock_socket () { return this; }
+
+ ssize_t recvfrom (void *ptr, size_t len, int flags,
+ struct sockaddr *from, int *fromlen);
+ ssize_t recvmsg (struct msghdr *msg, int flags);
+ void __reg3 read (void *ptr, size_t& len);
+ ssize_t __stdcall readv (const struct iovec *, int iovcnt, ssize_t tot = -1);
+ ssize_t __stdcall write (const void *ptr, size_t len);
+ ssize_t __stdcall writev (const struct iovec *, int iovcnt, ssize_t tot = -1);
+ int shutdown (int how);
+ int close ();
+
+ int ioctl (unsigned int cmd, void *);
+ int fcntl (int cmd, intptr_t);
+
+ /* select.cc */
+ select_record *select_read (select_stuff *);
+ select_record *select_write (select_stuff *);
+ select_record *select_except (select_stuff *);
+};
+
+class fhandler_socket_inet: public fhandler_socket_wsock
{
protected:
int af_local_connect () { return 0; }
- private:
- inline ssize_t recv_internal (struct _WSAMSG *wsamsg, bool use_recvmsg);
- inline ssize_t send_internal (struct _WSAMSG *wsamsg, int flags);
+ protected:
+ ssize_t recv_internal (struct _WSAMSG *wsamsg, bool use_recvmsg);
public:
fhandler_socket_inet ();
@@ -653,31 +697,14 @@ class fhandler_socket_inet: public fhandler_socket
int connect (const struct sockaddr *name, int namelen);
int getsockname (struct sockaddr *name, int *namelen);
int getpeername (struct sockaddr *name, int *namelen);
- int shutdown (int how);
- int close ();
- ssize_t recvfrom (void *ptr, size_t len, int flags,
- struct sockaddr *from, int *fromlen);
- ssize_t recvmsg (struct msghdr *msg, int flags);
- void __reg3 read (void *ptr, size_t& len);
- ssize_t __stdcall readv (const struct iovec *, int iovcnt, ssize_t tot = -1);
ssize_t sendto (const void *ptr, size_t len, int flags,
const struct sockaddr *to, int tolen);
ssize_t sendmsg (const struct msghdr *msg, int flags);
- ssize_t __stdcall write (const void *ptr, size_t len);
- ssize_t __stdcall writev (const struct iovec *, int iovcnt, ssize_t tot = -1);
int setsockopt (int level, int optname, const void *optval,
__socklen_t optlen);
int getsockopt (int level, int optname, const void *optval,
__socklen_t *optlen);
- int ioctl (unsigned int cmd, void *);
- int fcntl (int cmd, intptr_t);
-
- /* select.cc */
- select_record *select_read (select_stuff *);
- select_record *select_write (select_stuff *);
- select_record *select_except (select_stuff *);
-
/* from here on: CLONING */
fhandler_socket_inet (void *) {}
@@ -697,7 +724,7 @@ class fhandler_socket_inet: public fhandler_socket
}
};
-class fhandler_socket_local: public fhandler_socket
+class fhandler_socket_local: public fhandler_socket_wsock
{
protected:
char *sun_path;
@@ -729,9 +756,18 @@ class fhandler_socket_local: public fhandler_socket
int af_local_set_no_getpeereid ();
void af_local_set_sockpair_cred ();
- private:
- inline ssize_t recv_internal (struct _WSAMSG *wsamsg, bool use_recvmsg);
- inline ssize_t send_internal (struct _WSAMSG *wsamsg, int flags);
+ protected:
+ ssize_t recv_internal (struct _WSAMSG *wsamsg, bool use_recvmsg);
+
+ protected:
+ struct status_flags
+ {
+ unsigned no_getpeereid : 1;
+ public:
+ status_flags () : no_getpeereid (0) {}
+ } status;
+ public:
+ IMPLEMENT_STATUS_FLAG (bool, no_getpeereid)
public:
fhandler_socket_local ();
@@ -748,27 +784,15 @@ class fhandler_socket_local: public fhandler_socket
int connect (const struct sockaddr *name, int namelen);
int getsockname (struct sockaddr *name, int *namelen);
int getpeername (struct sockaddr *name, int *namelen);
- int shutdown (int how);
- int close ();
int getpeereid (pid_t *pid, uid_t *euid, gid_t *egid);
- ssize_t recvfrom (void *ptr, size_t len, int flags,
- struct sockaddr *from, int *fromlen);
- ssize_t recvmsg (struct msghdr *msg, int flags);
- void __reg3 read (void *ptr, size_t& len);
- ssize_t __stdcall readv (const struct iovec *, int iovcnt, ssize_t tot = -1);
ssize_t sendto (const void *ptr, size_t len, int flags,
const struct sockaddr *to, int tolen);
ssize_t sendmsg (const struct msghdr *msg, int flags);
- ssize_t __stdcall write (const void *ptr, size_t len);
- ssize_t __stdcall writev (const struct iovec *, int iovcnt, ssize_t tot = -1);
int setsockopt (int level, int optname, const void *optval,
__socklen_t optlen);
int getsockopt (int level, int optname, const void *optval,
__socklen_t *optlen);
- int ioctl (unsigned int cmd, void *);
- int fcntl (int cmd, intptr_t);
-
int __reg2 fstat (struct stat *buf);
int __reg2 fstatvfs (struct statvfs *buf);
int __reg1 fchmod (mode_t newmode);
@@ -776,11 +800,6 @@ class fhandler_socket_local: public fhandler_socket
int __reg3 facl (int, int, struct acl *);
int __reg2 link (const char *);
- /* select.cc */
- select_record *select_read (select_stuff *);
- select_record *select_write (select_stuff *);
- select_record *select_except (select_stuff *);
-
/* from here on: CLONING */
fhandler_socket_local (void *) {}
@@ -2357,7 +2376,6 @@ typedef union
char __pty_master[sizeof (fhandler_pty_master)];
char __registry[sizeof (fhandler_registry)];
char __serial[sizeof (fhandler_serial)];
- char __socket[sizeof (fhandler_socket)];
char __socket_inet[sizeof (fhandler_socket_inet)];
char __socket_local[sizeof (fhandler_socket_local)];
char __termios[sizeof (fhandler_termios)];
diff --git a/winsup/cygwin/fhandler_socket.cc b/winsup/cygwin/fhandler_socket.cc
index 0cdf6fa69..292e648c8 100644
--- a/winsup/cygwin/fhandler_socket.cc
+++ b/winsup/cygwin/fhandler_socket.cc
@@ -60,573 +60,14 @@ fhandler_socket::fhandler_socket () :
uid (myself->uid),
gid (myself->gid),
mode (S_IFSOCK | S_IRWXU | S_IRWXG | S_IRWXO),
- wsock_events (NULL),
- wsock_mtx (NULL),
- wsock_evt (NULL),
_rcvtimeo (INFINITE),
_sndtimeo (INFINITE),
- prot_info_ptr (NULL),
status ()
{
- need_fork_fixup (true);
}
fhandler_socket::~fhandler_socket ()
{
- if (prot_info_ptr)
- cfree (prot_info_ptr);
-}
-
-int
-fhandler_socket::set_socket_handle (SOCKET sock, int af, int type, int flags)
-{
- DWORD hdl_flags;
- bool lsp_fixup = false;
-
- /* Usually sockets are inheritable IFS objects. Unfortunately some virus
- scanners or other network-oriented software replace normal sockets
- with their own kind, which is running through a filter driver called
- "layered service provider" (LSP) which, fortunately, are deprecated.
-
- LSP sockets are not kernel objects. They are typically not marked as
- inheritable, nor are they IFS handles. They are in fact not inheritable
- to child processes, and it does not help to mark them inheritable via
- SetHandleInformation. Subsequent socket calls in the child process fail
- with error 10038, WSAENOTSOCK.
-
- There's a neat way to workaround these annoying LSP sockets. WSAIoctl
- allows to fetch the underlying base socket, which is a normal, inheritable
- IFS handle. So we fetch the base socket, duplicate it, and close the
- original socket. Now we have a standard IFS socket which (hopefully)
- works as expected.
-
- If that doesn't work for some reason, mark the sockets for duplication
- via WSADuplicateSocket/WSASocket. This requires to start the child
- process in SUSPENDED state so we only do this if really necessary. */
- if (!GetHandleInformation ((HANDLE) sock, &hdl_flags)
- || !(hdl_flags & HANDLE_FLAG_INHERIT))
- {
- int ret;
- SOCKET base_sock;
- DWORD bret;
-
- lsp_fixup = true;
- debug_printf ("LSP handle: %p", sock);
- ret = WSAIoctl (sock, SIO_BASE_HANDLE, NULL, 0, (void *) &base_sock,
- sizeof (base_sock), &bret, NULL, NULL);
- if (ret)
- debug_printf ("WSAIoctl: %u", WSAGetLastError ());
- else if (base_sock != sock)
- {
- if (GetHandleInformation ((HANDLE) base_sock, &hdl_flags)
- && (flags & HANDLE_FLAG_INHERIT))
- {
- if (!DuplicateHandle (GetCurrentProcess (), (HANDLE) base_sock,
- GetCurrentProcess (), (PHANDLE) &base_sock,
- 0, TRUE, DUPLICATE_SAME_ACCESS))
- debug_printf ("DuplicateHandle failed, %E");
- else
- {
- ::closesocket (sock);
- sock = base_sock;
- lsp_fixup = false;
- }
- }
- }
- }
- set_addr_family (af);
- set_socket_type (type);
- if (flags & SOCK_NONBLOCK)
- set_nonblocking (true);
- if (flags & SOCK_CLOEXEC)
- set_close_on_exec (true);
- set_io_handle ((HANDLE) sock);
- if (!init_events ())
- return -1;
- if (lsp_fixup)
- init_fixup_before ();
- set_flags (O_RDWR | O_BINARY);
- set_unique_id ();
- if (get_socket_type () == SOCK_DGRAM)
- {
- /* Workaround the problem that a missing listener on a UDP socket
- in a call to sendto will result in select/WSAEnumNetworkEvents
- reporting that the socket has pending data and a subsequent call
- to recvfrom will return -1 with error set to WSAECONNRESET.
-
- This problem is a regression introduced in Windows 2000.
- Instead of fixing the problem, a new socket IOCTL code has
- been added, see http://support.microsoft.com/kb/263823 */
- BOOL cr = FALSE;
- DWORD blen;
- if (WSAIoctl (sock, SIO_UDP_CONNRESET, &cr, sizeof cr, NULL, 0,
- &blen, NULL, NULL) == SOCKET_ERROR)
- debug_printf ("Reset SIO_UDP_CONNRESET: WinSock error %u",
- WSAGetLastError ());
- }
-#ifdef __x86_64__
- rmem () = 212992;
- wmem () = 212992;
-#else
- rmem () = 64512;
- wmem () = 64512;
-#endif
- return 0;
-}
-
-/* Maximum number of concurrently opened sockets from all Cygwin processes
- per session. Note that shared sockets (through dup/fork/exec) are
- counted as one socket. */
-#define NUM_SOCKS 2048U
-
-#define LOCK_EVENTS \
- if (wsock_mtx && \
- WaitForSingleObject (wsock_mtx, INFINITE) != WAIT_FAILED) \
- {
-
-#define UNLOCK_EVENTS \
- ReleaseMutex (wsock_mtx); \
- }
-
-static wsa_event wsa_events[NUM_SOCKS] __attribute__((section (".cygwin_dll_common"), shared));
-
-static LONG socket_serial_number __attribute__((section (".cygwin_dll_common"), shared));
-
-static HANDLE wsa_slot_mtx;
-
-static PWCHAR
-sock_shared_name (PWCHAR buf, LONG num)
-{
- __small_swprintf (buf, L"socket.%d", num);
- return buf;
-}
-
-static wsa_event *
-search_wsa_event_slot (LONG new_serial_number)
-{
- WCHAR name[32], searchname[32];
- UNICODE_STRING uname;
- OBJECT_ATTRIBUTES attr;
- NTSTATUS status;
-
- if (!wsa_slot_mtx)
- {
- RtlInitUnicodeString (&uname, sock_shared_name (name, 0));
- InitializeObjectAttributes (&attr, &uname, OBJ_INHERIT | OBJ_OPENIF,
- get_session_parent_dir (),
- everyone_sd (CYG_MUTANT_ACCESS));
- status = NtCreateMutant (&wsa_slot_mtx, CYG_MUTANT_ACCESS, &attr, FALSE);
- if (!NT_SUCCESS (status))
- api_fatal ("Couldn't create/open shared socket mutex %S, %y",
- &uname, status);
- }
- switch (WaitForSingleObject (wsa_slot_mtx, INFINITE))
- {
- case WAIT_OBJECT_0:
- case WAIT_ABANDONED:
- break;
- default:
- api_fatal ("WFSO failed for shared socket mutex, %E");
- break;
- }
- unsigned int slot = new_serial_number % NUM_SOCKS;
- while (wsa_events[slot].serial_number)
- {
- HANDLE searchmtx;
- RtlInitUnicodeString (&uname, sock_shared_name (searchname,
- wsa_events[slot].serial_number));
- InitializeObjectAttributes (&attr, &uname, 0, get_session_parent_dir (),
- NULL);
- status = NtOpenMutant (&searchmtx, READ_CONTROL, &attr);
- if (!NT_SUCCESS (status))
- break;
- /* Mutex still exists, attached socket is active, try next slot. */
- NtClose (searchmtx);
- slot = (slot + 1) % NUM_SOCKS;
- if (slot == (new_serial_number % NUM_SOCKS))
- {
- /* Did the whole array once. Too bad. */
- debug_printf ("No free socket slot");
- ReleaseMutex (wsa_slot_mtx);
- return NULL;
- }
- }
- memset (&wsa_events[slot], 0, sizeof (wsa_event));
- wsa_events[slot].serial_number = new_serial_number;
- ReleaseMutex (wsa_slot_mtx);
- return wsa_events + slot;
-}
-
-bool
-fhandler_socket::init_events ()
-{
- LONG new_serial_number;
- WCHAR name[32];
- UNICODE_STRING uname;
- OBJECT_ATTRIBUTES attr;
- NTSTATUS status;
-
- do
- {
- new_serial_number =
- InterlockedIncrement (&socket_serial_number);
- if (!new_serial_number) /* 0 is reserved for global mutex */
- InterlockedIncrement (&socket_serial_number);
- set_ino (new_serial_number);
- RtlInitUnicodeString (&uname, sock_shared_name (name, new_serial_number));
- InitializeObjectAttributes (&attr, &uname, OBJ_INHERIT | OBJ_OPENIF,
- get_session_parent_dir (),
- everyone_sd (CYG_MUTANT_ACCESS));
- status = NtCreateMutant (&wsock_mtx, CYG_MUTANT_ACCESS, &attr, FALSE);
- if (!NT_SUCCESS (status))
- {
- debug_printf ("NtCreateMutant(%S), %y", &uname, status);
- set_errno (ENOBUFS);
- return false;
- }
- if (status == STATUS_OBJECT_NAME_EXISTS)
- NtClose (wsock_mtx);
- }
- while (status == STATUS_OBJECT_NAME_EXISTS);
- if ((wsock_evt = CreateEvent (&sec_all, TRUE, FALSE, NULL))
- == WSA_INVALID_EVENT)
- {
- debug_printf ("CreateEvent, %E");
- set_errno (ENOBUFS);
- NtClose (wsock_mtx);
- return false;
- }
- if (WSAEventSelect (get_socket (), wsock_evt, EVENT_MASK) == SOCKET_ERROR)
- {
- debug_printf ("WSAEventSelect, %E");
- set_winsock_errno ();
- NtClose (wsock_evt);
- NtClose (wsock_mtx);
- return false;
- }
- if (!(wsock_events = search_wsa_event_slot (new_serial_number)))
- {
- set_errno (ENOBUFS);
- NtClose (wsock_evt);
- NtClose (wsock_mtx);
- return false;
- }
- if (get_socket_type () == SOCK_DGRAM)
- wsock_events->events = FD_WRITE;
- return true;
-}
-
-int
-fhandler_socket::evaluate_events (const long event_mask, long &events,
- const bool erase)
-{
- int ret = 0;
- long events_now = 0;
-
- WSANETWORKEVENTS evts = { 0 };
- if (!(WSAEnumNetworkEvents (get_socket (), wsock_evt, &evts)))
- {
- if (evts.lNetworkEvents)
- {
- LOCK_EVENTS;
- wsock_events->events |= evts.lNetworkEvents;
- events_now = (wsock_events->events & event_mask);
- if (evts.lNetworkEvents & FD_CONNECT)
- {
- wsock_events->connect_errorcode = evts.iErrorCode[FD_CONNECT_BIT];
-
- /* Setting the connect_state and calling the AF_LOCAL handshake
- here allows to handle this stuff from a single point. This
- is independent of FD_CONNECT being requested. Consider a
- server calling connect(2) and then immediately poll(2) with
- only polling for POLLIN (example: postfix), or select(2) just
- asking for descriptors ready to read.
-
- Something weird occurs in Winsock: If you fork off and call
- recv/send on the duplicated, already connected socket, another
- FD_CONNECT event is generated in the child process. This
- would trigger a call to af_local_connect which obviously fail.
- Avoid this by calling set_connect_state only if connect_state
- is connect_pending. */
- if (connect_state () == connect_pending)
- {
- if (wsock_events->connect_errorcode)
- connect_state (connect_failed);
- else if (af_local_connect ())
- {
- wsock_events->connect_errorcode = WSAGetLastError ();
- connect_state (connect_failed);
- }
- else
- connect_state (connected);
- }
- }
- UNLOCK_EVENTS;
- if ((evts.lNetworkEvents & FD_OOB) && wsock_events->owner)
- kill (wsock_events->owner, SIGURG);
- }
- }
-
- LOCK_EVENTS;
- if ((events = events_now) != 0
- || (events = (wsock_events->events & event_mask)) != 0)
- {
- if (events & FD_CONNECT)
- {
- int wsa_err = wsock_events->connect_errorcode;
- if (wsa_err)
- {
- /* CV 2014-04-23: This is really weird. If you call connect
- asynchronously on a socket and then select, an error like
- "Connection refused" is set in the event and in the SO_ERROR
- socket option. If you call connect, then dup, then select,
- the error is set in the event, but not in the SO_ERROR socket
- option, despite the dup'ed socket handle referring to the same
- socket. We're trying to workaround this problem here by
- taking the connect errorcode from the event and write it back
- into the SO_ERROR socket option.
-
- CV 2014-06-16: Call WSASetLastError *after* setsockopt since,
- apparently, setsockopt sets the last WSA error code to 0 on
- success. */
- ::setsockopt (get_socket (), SOL_SOCKET, SO_ERROR,
- (const char *) &wsa_err, sizeof wsa_err);
- WSASetLastError (wsa_err);
- ret = SOCKET_ERROR;
- }
- else
- wsock_events->events |= FD_WRITE;
- wsock_events->events &= ~FD_CONNECT;
- wsock_events->connect_errorcode = 0;
- }
- /* This test makes accept/connect behave as on Linux when accept/connect
- is called on a socket for which shutdown has been called. The second
- half of this code is in the shutdown method. */
- if (events & FD_CLOSE)
- {
- if ((event_mask & FD_ACCEPT) && saw_shutdown_read ())
- {
- WSASetLastError (WSAEINVAL);
- ret = SOCKET_ERROR;
- }
- if (event_mask & FD_CONNECT)
- {
- WSASetLastError (WSAECONNRESET);
- ret = SOCKET_ERROR;
- }
- }
- if (erase)
- wsock_events->events &= ~(events & ~(FD_WRITE | FD_CLOSE));
- }
- UNLOCK_EVENTS;
-
- return ret;
-}
-
-int
-fhandler_socket::wait_for_events (const long event_mask, const DWORD flags)
-{
- if (async_io ())
- return 0;
-
- int ret;
- long events = 0;
- DWORD wfmo_timeout = 50;
- DWORD timeout;
-
- WSAEVENT ev[3] = { wsock_evt, NULL, NULL };
- wait_signal_arrived here (ev[1]);
- DWORD ev_cnt = 2;
- if ((ev[2] = pthread::get_cancel_event ()) != NULL)
- ++ev_cnt;
-
- if (is_nonblocking () || (flags & MSG_DONTWAIT))
- timeout = 0;
- else if (event_mask & FD_READ)
- timeout = rcvtimeo ();
- else if (event_mask & FD_WRITE)
- timeout = sndtimeo ();
- else
- timeout = INFINITE;
-
- while (!(ret = evaluate_events (event_mask, events, !(flags & MSG_PEEK)))
- && !events)
- {
- if (timeout == 0)
- {
- WSASetLastError (WSAEWOULDBLOCK);
- return SOCKET_ERROR;
- }
-
- if (timeout < wfmo_timeout)
- wfmo_timeout = timeout;
- switch (WSAWaitForMultipleEvents (ev_cnt, ev, FALSE, wfmo_timeout, FALSE))
- {
- case WSA_WAIT_TIMEOUT:
- case WSA_WAIT_EVENT_0:
- if (timeout != INFINITE)
- timeout -= wfmo_timeout;
- break;
-
- case WSA_WAIT_EVENT_0 + 1:
- if (_my_tls.call_signal_handler ())
- break;
- WSASetLastError (WSAEINTR);
- return SOCKET_ERROR;
-
- case WSA_WAIT_EVENT_0 + 2:
- pthread::static_cancel_self ();
- break;
-
- default:
- /* wsock_evt can be NULL. We're generating the same errno values
- as for sockets on which shutdown has been called. */
- if (WSAGetLastError () != WSA_INVALID_HANDLE)
- WSASetLastError (WSAEFAULT);
- else
- WSASetLastError ((event_mask & FD_CONNECT) ? WSAECONNRESET
- : WSAEINVAL);
- return SOCKET_ERROR;
- }
- }
- return ret;
-}
-
-void
-fhandler_socket::release_events ()
-{
- if (WaitForSingleObject (wsock_mtx, INFINITE) != WAIT_FAILED)
- {
- HANDLE evt = wsock_evt;
- HANDLE mtx = wsock_mtx;
-
- wsock_evt = wsock_mtx = NULL;
- ReleaseMutex (mtx);
- NtClose (evt);
- NtClose (mtx);
- }
-}
-
-void
-fhandler_socket::set_close_on_exec (bool val)
-{
- set_no_inheritance (wsock_mtx, val);
- set_no_inheritance (wsock_evt, val);
- if (need_fixup_before ())
- {
- close_on_exec (val);
- debug_printf ("set close_on_exec for %s to %d", get_name (), val);
- }
- else
- fhandler_base::set_close_on_exec (val);
-}
-
-/* Called if a freshly created socket is not inheritable. In that case we
- have to use fixup_before_fork_exec. See comment in set_socket_handle for
- a description of the problem. */
-void
-fhandler_socket::init_fixup_before ()
-{
- prot_info_ptr = (LPWSAPROTOCOL_INFOW)
- cmalloc_abort (HEAP_BUF, sizeof (WSAPROTOCOL_INFOW));
- cygheap->fdtab.inc_need_fixup_before ();
-}
-
-int
-fhandler_socket::fixup_before_fork_exec (DWORD win_pid)
-{
- SOCKET ret = WSADuplicateSocketW (get_socket (), win_pid, prot_info_ptr);
- if (ret)
- set_winsock_errno ();
- else
- debug_printf ("WSADuplicateSocket succeeded (%x)", prot_info_ptr->dwProviderReserved);
- return (int) ret;
-}
-
-void
-fhandler_socket::fixup_after_fork (HANDLE parent)
-{
- fork_fixup (parent, wsock_mtx, "wsock_mtx");
- fork_fixup (parent, wsock_evt, "wsock_evt");
-
- if (!need_fixup_before ())
- {
- fhandler_base::fixup_after_fork (parent);
- return;
- }
-
- SOCKET new_sock = WSASocketW (FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO,
- FROM_PROTOCOL_INFO, prot_info_ptr, 0,
- WSA_FLAG_OVERLAPPED);
- if (new_sock == INVALID_SOCKET)
- {
- set_winsock_errno ();
- set_io_handle ((HANDLE) INVALID_SOCKET);
- }
- else
- {
- /* Even though the original socket was not inheritable, the duplicated
- socket is potentially inheritable again. */
- SetHandleInformation ((HANDLE) new_sock, HANDLE_FLAG_INHERIT, 0);
- set_io_handle ((HANDLE) new_sock);
- debug_printf ("WSASocket succeeded (%p)", new_sock);
- }
-}
-
-void
-fhandler_socket::fixup_after_exec ()
-{
- if (need_fixup_before () && !close_on_exec ())
- fixup_after_fork (NULL);
-}
-
-int
-fhandler_socket::dup (fhandler_base *child, int flags)
-{
- debug_printf ("here");
- fhandler_socket *fhs = (fhandler_socket *) child;
-
- if (!DuplicateHandle (GetCurrentProcess (), wsock_mtx,
- GetCurrentProcess (), &fhs->wsock_mtx,
- 0, TRUE, DUPLICATE_SAME_ACCESS))
- {
- __seterrno ();
- return -1;
- }
- if (!DuplicateHandle (GetCurrentProcess (), wsock_evt,
- GetCurrentProcess (), &fhs->wsock_evt,
- 0, TRUE, DUPLICATE_SAME_ACCESS))
- {
- __seterrno ();
- NtClose (fhs->wsock_mtx);
- return -1;
- }
- if (!need_fixup_before ())
- {
- int ret = fhandler_base::dup (child, flags);
- if (ret)
- {
- NtClose (fhs->wsock_evt);
- NtClose (fhs->wsock_mtx);
- }
- return ret;
- }
-
- cygheap->user.deimpersonate ();
- fhs->init_fixup_before ();
- fhs->set_io_handle (get_io_handle ());
- int ret = fhs->fixup_before_fork_exec (GetCurrentProcessId ());
- cygheap->user.reimpersonate ();
- if (!ret)
- {
- fhs->fixup_after_fork (GetCurrentProcess ());
- if (fhs->get_io_handle() != (HANDLE) INVALID_SOCKET)
- return 0;
- }
- cygheap->fdtab.dec_need_fixup_before ();
- NtClose (fhs->wsock_evt);
- NtClose (fhs->wsock_mtx);
- return -1;
}
char *
diff --git a/winsup/cygwin/fhandler_socket_inet.cc b/winsup/cygwin/fhandler_socket_inet.cc
index b2bc1934a..0668c1063 100644
--- a/winsup/cygwin/fhandler_socket_inet.cc
+++ b/winsup/cygwin/fhandler_socket_inet.cc
@@ -59,6 +59,89 @@
ReleaseMutex (wsock_mtx); \
}
+/* Maximum number of concurrently opened sockets from all Cygwin processes
+ per session. Note that shared sockets (through dup/fork/exec) are
+ counted as one socket. */
+#define NUM_SOCKS 2048U
+
+#define LOCK_EVENTS \
+ if (wsock_mtx && \
+ WaitForSingleObject (wsock_mtx, INFINITE) != WAIT_FAILED) \
+ {
+
+#define UNLOCK_EVENTS \
+ ReleaseMutex (wsock_mtx); \
+ }
+
+static wsa_event wsa_events[NUM_SOCKS] __attribute__((section (".cygwin_dll_common"), shared));
+
+static LONG socket_serial_number __attribute__((section (".cygwin_dll_common"), shared));
+
+static HANDLE wsa_slot_mtx;
+
+static PWCHAR
+sock_shared_name (PWCHAR buf, LONG num)
+{
+ __small_swprintf (buf, L"socket.%d", num);
+ return buf;
+}
+
+static wsa_event *
+search_wsa_event_slot (LONG new_serial_number)
+{
+ WCHAR name[32], searchname[32];
+ UNICODE_STRING uname;
+ OBJECT_ATTRIBUTES attr;
+ NTSTATUS status;
+
+ if (!wsa_slot_mtx)
+ {
+ RtlInitUnicodeString (&uname, sock_shared_name (name, 0));
+ InitializeObjectAttributes (&attr, &uname, OBJ_INHERIT | OBJ_OPENIF,
+ get_session_parent_dir (),
+ everyone_sd (CYG_MUTANT_ACCESS));
+ status = NtCreateMutant (&wsa_slot_mtx, CYG_MUTANT_ACCESS, &attr, FALSE);
+ if (!NT_SUCCESS (status))
+ api_fatal ("Couldn't create/open shared socket mutex %S, %y",
+ &uname, status);
+ }
+ switch (WaitForSingleObject (wsa_slot_mtx, INFINITE))
+ {
+ case WAIT_OBJECT_0:
+ case WAIT_ABANDONED:
+ break;
+ default:
+ api_fatal ("WFSO failed for shared socket mutex, %E");
+ break;
+ }
+ unsigned int slot = new_serial_number % NUM_SOCKS;
+ while (wsa_events[slot].serial_number)
+ {
+ HANDLE searchmtx;
+ RtlInitUnicodeString (&uname, sock_shared_name (searchname,
+ wsa_events[slot].serial_number));
+ InitializeObjectAttributes (&attr, &uname, 0, get_session_parent_dir (),
+ NULL);
+ status = NtOpenMutant (&searchmtx, READ_CONTROL, &attr);
+ if (!NT_SUCCESS (status))
+ break;
+ /* Mutex still exists, attached socket is active, try next slot. */
+ NtClose (searchmtx);
+ slot = (slot + 1) % NUM_SOCKS;
+ if (slot == (new_serial_number % NUM_SOCKS))
+ {
+ /* Did the whole array once. Too bad. */
+ debug_printf ("No free socket slot");
+ ReleaseMutex (wsa_slot_mtx);
+ return NULL;
+ }
+ }
+ memset (&wsa_events[slot], 0, sizeof (wsa_event));
+ wsa_events[slot].serial_number = new_serial_number;
+ ReleaseMutex (wsa_slot_mtx);
+ return wsa_events + slot;
+}
+
/* cygwin internal: map sockaddr into internet domain address */
static int
get_inet_addr_inet (const struct sockaddr *in, int inlen,
@@ -123,8 +206,496 @@ convert_ws1_ip_optname (int optname)
: ws2_optname[optname];
}
+fhandler_socket_wsock::fhandler_socket_wsock () :
+ fhandler_socket (),
+ wsock_events (NULL),
+ wsock_mtx (NULL),
+ wsock_evt (NULL),
+ prot_info_ptr (NULL),
+ status ()
+{
+ need_fork_fixup (true);
+}
+
+fhandler_socket_wsock::~fhandler_socket_wsock ()
+{
+ if (prot_info_ptr)
+ cfree (prot_info_ptr);
+}
+
+bool
+fhandler_socket_wsock::init_events ()
+{
+ LONG new_serial_number;
+ WCHAR name[32];
+ UNICODE_STRING uname;
+ OBJECT_ATTRIBUTES attr;
+ NTSTATUS status;
+
+ do
+ {
+ new_serial_number =
+ InterlockedIncrement (&socket_serial_number);
+ if (!new_serial_number) /* 0 is reserved for global mutex */
+ InterlockedIncrement (&socket_serial_number);
+ set_ino (new_serial_number);
+ RtlInitUnicodeString (&uname, sock_shared_name (name, new_serial_number));
+ InitializeObjectAttributes (&attr, &uname, OBJ_INHERIT | OBJ_OPENIF,
+ get_session_parent_dir (),
+ everyone_sd (CYG_MUTANT_ACCESS));
+ status = NtCreateMutant (&wsock_mtx, CYG_MUTANT_ACCESS, &attr, FALSE);
+ if (!NT_SUCCESS (status))
+ {
+ debug_printf ("NtCreateMutant(%S), %y", &uname, status);
+ set_errno (ENOBUFS);
+ return false;
+ }
+ if (status == STATUS_OBJECT_NAME_EXISTS)
+ NtClose (wsock_mtx);
+ }
+ while (status == STATUS_OBJECT_NAME_EXISTS);
+ if ((wsock_evt = CreateEvent (&sec_all, TRUE, FALSE, NULL))
+ == WSA_INVALID_EVENT)
+ {
+ debug_printf ("CreateEvent, %E");
+ set_errno (ENOBUFS);
+ NtClose (wsock_mtx);
+ return false;
+ }
+ if (WSAEventSelect (get_socket (), wsock_evt, EVENT_MASK) == SOCKET_ERROR)
+ {
+ debug_printf ("WSAEventSelect, %E");
+ set_winsock_errno ();
+ NtClose (wsock_evt);
+ NtClose (wsock_mtx);
+ return false;
+ }
+ if (!(wsock_events = search_wsa_event_slot (new_serial_number)))
+ {
+ set_errno (ENOBUFS);
+ NtClose (wsock_evt);
+ NtClose (wsock_mtx);
+ return false;
+ }
+ if (get_socket_type () == SOCK_DGRAM)
+ wsock_events->events = FD_WRITE;
+ return true;
+}
+
+int
+fhandler_socket_wsock::evaluate_events (const long event_mask, long &events,
+ const bool erase)
+{
+ int ret = 0;
+ long events_now = 0;
+
+ WSANETWORKEVENTS evts = { 0 };
+ if (!(WSAEnumNetworkEvents (get_socket (), wsock_evt, &evts)))
+ {
+ if (evts.lNetworkEvents)
+ {
+ LOCK_EVENTS;
+ wsock_events->events |= evts.lNetworkEvents;
+ events_now = (wsock_events->events & event_mask);
+ if (evts.lNetworkEvents & FD_CONNECT)
+ {
+ wsock_events->connect_errorcode = evts.iErrorCode[FD_CONNECT_BIT];
+
+ /* Setting the connect_state and calling the AF_LOCAL handshake
+ here allows to handle this stuff from a single point. This
+ is independent of FD_CONNECT being requested. Consider a
+ server calling connect(2) and then immediately poll(2) with
+ only polling for POLLIN (example: postfix), or select(2) just
+ asking for descriptors ready to read.
+
+ Something weird occurs in Winsock: If you fork off and call
+ recv/send on the duplicated, already connected socket, another
+ FD_CONNECT event is generated in the child process. This
+ would trigger a call to af_local_connect which obviously fail.
+ Avoid this by calling set_connect_state only if connect_state
+ is connect_pending. */
+ if (connect_state () == connect_pending)
+ {
+ if (wsock_events->connect_errorcode)
+ connect_state (connect_failed);
+ else if (af_local_connect ())
+ {
+ wsock_events->connect_errorcode = WSAGetLastError ();
+ connect_state (connect_failed);
+ }
+ else
+ connect_state (connected);
+ }
+ }
+ UNLOCK_EVENTS;
+ if ((evts.lNetworkEvents & FD_OOB) && wsock_events->owner)
+ kill (wsock_events->owner, SIGURG);
+ }
+ }
+
+ LOCK_EVENTS;
+ if ((events = events_now) != 0
+ || (events = (wsock_events->events & event_mask)) != 0)
+ {
+ if (events & FD_CONNECT)
+ {
+ int wsa_err = wsock_events->connect_errorcode;
+ if (wsa_err)
+ {
+ /* CV 2014-04-23: This is really weird. If you call connect
+ asynchronously on a socket and then select, an error like
+ "Connection refused" is set in the event and in the SO_ERROR
+ socket option. If you call connect, then dup, then select,
+ the error is set in the event, but not in the SO_ERROR socket
+ option, despite the dup'ed socket handle referring to the same
+ socket. We're trying to workaround this problem here by
+ taking the connect errorcode from the event and write it back
+ into the SO_ERROR socket option.
+
+ CV 2014-06-16: Call WSASetLastError *after* setsockopt since,
+ apparently, setsockopt sets the last WSA error code to 0 on
+ success. */
+ ::setsockopt (get_socket (), SOL_SOCKET, SO_ERROR,
+ (const char *) &wsa_err, sizeof wsa_err);
+ WSASetLastError (wsa_err);
+ ret = SOCKET_ERROR;
+ }
+ else
+ wsock_events->events |= FD_WRITE;
+ wsock_events->events &= ~FD_CONNECT;
+ wsock_events->connect_errorcode = 0;
+ }
+ /* This test makes accept/connect behave as on Linux when accept/connect
+ is called on a socket for which shutdown has been called. The second
+ half of this code is in the shutdown method. */
+ if (events & FD_CLOSE)
+ {
+ if ((event_mask & FD_ACCEPT) && saw_shutdown_read ())
+ {
+ WSASetLastError (WSAEINVAL);
+ ret = SOCKET_ERROR;
+ }
+ if (event_mask & FD_CONNECT)
+ {
+ WSASetLastError (WSAECONNRESET);
+ ret = SOCKET_ERROR;
+ }
+ }
+ if (erase)
+ wsock_events->events &= ~(events & ~(FD_WRITE | FD_CLOSE));
+ }
+ UNLOCK_EVENTS;
+
+ return ret;
+}
+
+int
+fhandler_socket_wsock::wait_for_events (const long event_mask,
+ const DWORD flags)
+{
+ if (async_io ())
+ return 0;
+
+ int ret;
+ long events = 0;
+ DWORD wfmo_timeout = 50;
+ DWORD timeout;
+
+ WSAEVENT ev[3] = { wsock_evt, NULL, NULL };
+ wait_signal_arrived here (ev[1]);
+ DWORD ev_cnt = 2;
+ if ((ev[2] = pthread::get_cancel_event ()) != NULL)
+ ++ev_cnt;
+
+ if (is_nonblocking () || (flags & MSG_DONTWAIT))
+ timeout = 0;
+ else if (event_mask & FD_READ)
+ timeout = rcvtimeo ();
+ else if (event_mask & FD_WRITE)
+ timeout = sndtimeo ();
+ else
+ timeout = INFINITE;
+
+ while (!(ret = evaluate_events (event_mask, events, !(flags & MSG_PEEK)))
+ && !events)
+ {
+ if (timeout == 0)
+ {
+ WSASetLastError (WSAEWOULDBLOCK);
+ return SOCKET_ERROR;
+ }
+
+ if (timeout < wfmo_timeout)
+ wfmo_timeout = timeout;
+ switch (WSAWaitForMultipleEvents (ev_cnt, ev, FALSE, wfmo_timeout, FALSE))
+ {
+ case WSA_WAIT_TIMEOUT:
+ case WSA_WAIT_EVENT_0:
+ if (timeout != INFINITE)
+ timeout -= wfmo_timeout;
+ break;
+
+ case WSA_WAIT_EVENT_0 + 1:
+ if (_my_tls.call_signal_handler ())
+ break;
+ WSASetLastError (WSAEINTR);
+ return SOCKET_ERROR;
+
+ case WSA_WAIT_EVENT_0 + 2:
+ pthread::static_cancel_self ();
+ break;
+
+ default:
+ /* wsock_evt can be NULL. We're generating the same errno values
+ as for sockets on which shutdown has been called. */
+ if (WSAGetLastError () != WSA_INVALID_HANDLE)
+ WSASetLastError (WSAEFAULT);
+ else
+ WSASetLastError ((event_mask & FD_CONNECT) ? WSAECONNRESET
+ : WSAEINVAL);
+ return SOCKET_ERROR;
+ }
+ }
+ return ret;
+}
+
+void
+fhandler_socket_wsock::release_events ()
+{
+ if (WaitForSingleObject (wsock_mtx, INFINITE) != WAIT_FAILED)
+ {
+ HANDLE evt = wsock_evt;
+ HANDLE mtx = wsock_mtx;
+
+ wsock_evt = wsock_mtx = NULL;
+ ReleaseMutex (mtx);
+ NtClose (evt);
+ NtClose (mtx);
+ }
+}
+
+void
+fhandler_socket_wsock::set_close_on_exec (bool val)
+{
+ set_no_inheritance (wsock_mtx, val);
+ set_no_inheritance (wsock_evt, val);
+ if (need_fixup_before ())
+ {
+ close_on_exec (val);
+ debug_printf ("set close_on_exec for %s to %d", get_name (), val);
+ }
+ else
+ fhandler_base::set_close_on_exec (val);
+}
+
+/* Called if a freshly created socket is not inheritable. In that case we
+ have to use fixup_before_fork_exec. See comment in set_socket_handle for
+ a description of the problem. */
+void
+fhandler_socket_wsock::init_fixup_before ()
+{
+ prot_info_ptr = (LPWSAPROTOCOL_INFOW)
+ cmalloc_abort (HEAP_BUF, sizeof (WSAPROTOCOL_INFOW));
+ cygheap->fdtab.inc_need_fixup_before ();
+}
+
+int
+fhandler_socket_wsock::fixup_before_fork_exec (DWORD win_pid)
+{
+ SOCKET ret = WSADuplicateSocketW (get_socket (), win_pid, prot_info_ptr);
+ if (ret)
+ set_winsock_errno ();
+ else
+ debug_printf ("WSADuplicateSocket succeeded (%x)", prot_info_ptr->dwProviderReserved);
+ return (int) ret;
+}
+
+void
+fhandler_socket_wsock::fixup_after_fork (HANDLE parent)
+{
+ fork_fixup (parent, wsock_mtx, "wsock_mtx");
+ fork_fixup (parent, wsock_evt, "wsock_evt");
+
+ if (!need_fixup_before ())
+ {
+ fhandler_base::fixup_after_fork (parent);
+ return;
+ }
+
+ SOCKET new_sock = WSASocketW (FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO,
+ FROM_PROTOCOL_INFO, prot_info_ptr, 0,
+ WSA_FLAG_OVERLAPPED);
+ if (new_sock == INVALID_SOCKET)
+ {
+ set_winsock_errno ();
+ set_io_handle ((HANDLE) INVALID_SOCKET);
+ }
+ else
+ {
+ /* Even though the original socket was not inheritable, the duplicated
+ socket is potentially inheritable again. */
+ SetHandleInformation ((HANDLE) new_sock, HANDLE_FLAG_INHERIT, 0);
+ set_io_handle ((HANDLE) new_sock);
+ debug_printf ("WSASocket succeeded (%p)", new_sock);
+ }
+}
+
+void
+fhandler_socket_wsock::fixup_after_exec ()
+{
+ if (need_fixup_before () && !close_on_exec ())
+ fixup_after_fork (NULL);
+}
+
+int
+fhandler_socket_wsock::dup (fhandler_base *child, int flags)
+{
+ debug_printf ("here");
+ fhandler_socket_wsock *fhs = (fhandler_socket_wsock *) child;
+
+ if (!DuplicateHandle (GetCurrentProcess (), wsock_mtx,
+ GetCurrentProcess (), &fhs->wsock_mtx,
+ 0, TRUE, DUPLICATE_SAME_ACCESS))
+ {
+ __seterrno ();
+ return -1;
+ }
+ if (!DuplicateHandle (GetCurrentProcess (), wsock_evt,
+ GetCurrentProcess (), &fhs->wsock_evt,
+ 0, TRUE, DUPLICATE_SAME_ACCESS))
+ {
+ __seterrno ();
+ NtClose (fhs->wsock_mtx);
+ return -1;
+ }
+ if (!need_fixup_before ())
+ {
+ int ret = fhandler_base::dup (child, flags);
+ if (ret)
+ {
+ NtClose (fhs->wsock_evt);
+ NtClose (fhs->wsock_mtx);
+ }
+ return ret;
+ }
+
+ cygheap->user.deimpersonate ();
+ fhs->init_fixup_before ();
+ fhs->set_io_handle (get_io_handle ());
+ int ret = fhs->fixup_before_fork_exec (GetCurrentProcessId ());
+ cygheap->user.reimpersonate ();
+ if (!ret)
+ {
+ fhs->fixup_after_fork (GetCurrentProcess ());
+ if (fhs->get_io_handle() != (HANDLE) INVALID_SOCKET)
+ return 0;
+ }
+ cygheap->fdtab.dec_need_fixup_before ();
+ NtClose (fhs->wsock_evt);
+ NtClose (fhs->wsock_mtx);
+ return -1;
+}
+
+int
+fhandler_socket_wsock::set_socket_handle (SOCKET sock, int af, int type,
+ int flags)
+{
+ DWORD hdl_flags;
+ bool lsp_fixup = false;
+
+ /* Usually sockets are inheritable IFS objects. Unfortunately some virus
+ scanners or other network-oriented software replace normal sockets
+ with their own kind, which is running through a filter driver called
+ "layered service provider" (LSP) which, fortunately, are deprecated.
+
+ LSP sockets are not kernel objects. They are typically not marked as
+ inheritable, nor are they IFS handles. They are in fact not inheritable
+ to child processes, and it does not help to mark them inheritable via
+ SetHandleInformation. Subsequent socket calls in the child process fail
+ with error 10038, WSAENOTSOCK.
+
+ There's a neat way to workaround these annoying LSP sockets. WSAIoctl
+ allows to fetch the underlying base socket, which is a normal, inheritable
+ IFS handle. So we fetch the base socket, duplicate it, and close the
+ original socket. Now we have a standard IFS socket which (hopefully)
+ works as expected.
+
+ If that doesn't work for some reason, mark the sockets for duplication
+ via WSADuplicateSocket/WSASocket. This requires to start the child
+ process in SUSPENDED state so we only do this if really necessary. */
+ if (!GetHandleInformation ((HANDLE) sock, &hdl_flags)
+ || !(hdl_flags & HANDLE_FLAG_INHERIT))
+ {
+ int ret;
+ SOCKET base_sock;
+ DWORD bret;
+
+ lsp_fixup = true;
+ debug_printf ("LSP handle: %p", sock);
+ ret = WSAIoctl (sock, SIO_BASE_HANDLE, NULL, 0, (void *) &base_sock,
+ sizeof (base_sock), &bret, NULL, NULL);
+ if (ret)
+ debug_printf ("WSAIoctl: %u", WSAGetLastError ());
+ else if (base_sock != sock)
+ {
+ if (GetHandleInformation ((HANDLE) base_sock, &hdl_flags)
+ && (flags & HANDLE_FLAG_INHERIT))
+ {
+ if (!DuplicateHandle (GetCurrentProcess (), (HANDLE) base_sock,
+ GetCurrentProcess (), (PHANDLE) &base_sock,
+ 0, TRUE, DUPLICATE_SAME_ACCESS))
+ debug_printf ("DuplicateHandle failed, %E");
+ else
+ {
+ ::closesocket (sock);
+ sock = base_sock;
+ lsp_fixup = false;
+ }
+ }
+ }
+ }
+ set_addr_family (af);
+ set_socket_type (type);
+ if (flags & SOCK_NONBLOCK)
+ set_nonblocking (true);
+ if (flags & SOCK_CLOEXEC)
+ set_close_on_exec (true);
+ set_io_handle ((HANDLE) sock);
+ if (!init_events ())
+ return -1;
+ if (lsp_fixup)
+ init_fixup_before ();
+ set_flags (O_RDWR | O_BINARY);
+ set_unique_id ();
+ if (get_socket_type () == SOCK_DGRAM)
+ {
+ /* Workaround the problem that a missing listener on a UDP socket
+ in a call to sendto will result in select/WSAEnumNetworkEvents
+ reporting that the socket has pending data and a subsequent call
+ to recvfrom will return -1 with error set to WSAECONNRESET.
+
+ This problem is a regression introduced in Windows 2000.
+ Instead of fixing the problem, a new socket IOCTL code has
+ been added, see http://support.microsoft.com/kb/263823 */
+ BOOL cr = FALSE;
+ DWORD blen;
+ if (WSAIoctl (sock, SIO_UDP_CONNRESET, &cr, sizeof cr, NULL, 0,
+ &blen, NULL, NULL) == SOCKET_ERROR)
+ debug_printf ("Reset SIO_UDP_CONNRESET: WinSock error %u",
+ WSAGetLastError ());
+ }
+#ifdef __x86_64__
+ rmem () = 212992;
+ wmem () = 212992;
+#else
+ rmem () = 64512;
+ wmem () = 64512;
+#endif
+ return 0;
+}
+
fhandler_socket_inet::fhandler_socket_inet () :
- fhandler_socket ()
+ fhandler_socket_wsock ()
{
}
@@ -398,7 +969,7 @@ fhandler_socket_inet::getpeername (struct sockaddr *name, int *namelen)
}
int
-fhandler_socket_inet::shutdown (int how)
+fhandler_socket_wsock::shutdown (int how)
{
int res = ::shutdown (get_socket (), how);
@@ -437,7 +1008,7 @@ fhandler_socket_inet::shutdown (int how)
}
int
-fhandler_socket_inet::close ()
+fhandler_socket_wsock::close ()
{
int res = 0;
@@ -458,12 +1029,10 @@ fhandler_socket_inet::close ()
}
WSASetLastError (0);
}
-
- debug_printf ("%d = fhandler_socket::close()", res);
return res;
}
-inline ssize_t
+ssize_t
fhandler_socket_inet::recv_internal (LPWSAMSG wsamsg, bool use_recvmsg)
{
ssize_t res = 0;
@@ -594,8 +1163,8 @@ fhandler_socket_inet::recv_internal (LPWSAMSG wsamsg, bool use_recvmsg)
}
ssize_t
-fhandler_socket_inet::recvfrom (void *in_ptr, size_t len, int flags,
- struct sockaddr *from, int *fromlen)
+fhandler_socket_wsock::recvfrom (void *in_ptr, size_t len, int flags,
+ struct sockaddr *from, int *fromlen)
{
char *ptr = (char *) in_ptr;
@@ -630,7 +1199,7 @@ fhandler_socket_inet::recvfrom (void *in_ptr, size_t len, int flags,
}
ssize_t
-fhandler_socket_inet::recvmsg (struct msghdr *msg, int flags)
+fhandler_socket_wsock::recvmsg (struct msghdr *msg, int flags)
{
/* Disappointing but true: Even if WSARecvMsg is supported, it's only
supported for datagram and raw sockets. */
@@ -665,7 +1234,7 @@ fhandler_socket_inet::recvmsg (struct msghdr *msg, int flags)
}
void __reg3
-fhandler_socket_inet::read (void *in_ptr, size_t& len)
+fhandler_socket_wsock::read (void *in_ptr, size_t& len)
{
char *ptr = (char *) in_ptr;
@@ -692,8 +1261,8 @@ fhandler_socket_inet::read (void *in_ptr, size_t& len)
}
ssize_t
-fhandler_socket_inet::readv (const struct iovec *const iov, const int iovcnt,
- ssize_t tot)
+fhandler_socket_wsock::readv (const struct iovec *const iov, const int iovcnt,
+ ssize_t tot)
{
WSABUF wsabuf[iovcnt];
WSABUF *wsaptr = wsabuf + iovcnt;
@@ -707,8 +1276,8 @@ fhandler_socket_inet::readv (const struct iovec *const iov, const int iovcnt,
return recv_internal (&wsamsg, false);
}
-inline ssize_t
-fhandler_socket_inet::send_internal (struct _WSAMSG *wsamsg, int flags)
+ssize_t
+fhandler_socket_wsock::send_internal (struct _WSAMSG *wsamsg, int flags)
{
ssize_t res = 0;
DWORD ret = 0, sum = 0;
@@ -891,7 +1460,7 @@ fhandler_socket_inet::sendmsg (const struct msghdr *msg, int flags)
}
ssize_t
-fhandler_socket_inet::write (const void *in_ptr, size_t len)
+fhandler_socket_wsock::write (const void *in_ptr, size_t len)
{
char *ptr = (char *) in_ptr;
@@ -917,8 +1486,8 @@ fhandler_socket_inet::write (const void *in_ptr, size_t len)
}
ssize_t
-fhandler_socket_inet::writev (const struct iovec *const iov, const int iovcnt,
- ssize_t tot)
+fhandler_socket_wsock::writev (const struct iovec *const iov, const int iovcnt,
+ ssize_t tot)
{
WSABUF wsabuf[iovcnt];
WSABUF *wsaptr = wsabuf;
@@ -1219,7 +1788,7 @@ fhandler_socket_inet::getsockopt (int level, int optname, const void *optval,
}
int
-fhandler_socket_inet::ioctl (unsigned int cmd, void *p)
+fhandler_socket_wsock::ioctl (unsigned int cmd, void *p)
{
int res;
@@ -1287,7 +1856,7 @@ fhandler_socket_inet::ioctl (unsigned int cmd, void *p)
}
int
-fhandler_socket_inet::fcntl (int cmd, intptr_t arg)
+fhandler_socket_wsock::fcntl (int cmd, intptr_t arg)
{
int res = 0;
diff --git a/winsup/cygwin/fhandler_socket_local.cc b/winsup/cygwin/fhandler_socket_local.cc
index 298a378e3..ca3844291 100644
--- a/winsup/cygwin/fhandler_socket_local.cc
+++ b/winsup/cygwin/fhandler_socket_local.cc
@@ -221,9 +221,10 @@ get_ext_funcptr (SOCKET sock, void *funcptr)
}
fhandler_socket_local::fhandler_socket_local () :
- fhandler_socket (),
+ fhandler_socket_wsock (),
sun_path (NULL),
- peer_sun_path (NULL)
+ peer_sun_path (NULL),
+ status ()
{
}
@@ -1044,73 +1045,7 @@ fhandler_socket_local::getpeername (struct sockaddr *name, int *namelen)
return res;
}
-int
-fhandler_socket_local::shutdown (int how)
-{
- int res = ::shutdown (get_socket (), how);
-
- /* Linux allows to call shutdown for any socket, even if it's not connected.
- This also disables to call accept on this socket, if shutdown has been
- called with the SHUT_RD or SHUT_RDWR parameter. In contrast, WinSock
- only allows to call shutdown on a connected socket. The accept function
- is in no way affected. So, what we do here is to fake success, and to
- change the event settings so that an FD_CLOSE event is triggered for the
- calling Cygwin function. The evaluate_events method handles the call
- from accept specially to generate a Linux-compatible behaviour. */
- if (res && WSAGetLastError () != WSAENOTCONN)
- set_winsock_errno ();
- else
- {
- res = 0;
- switch (how)
- {
- case SHUT_RD:
- saw_shutdown_read (true);
- wsock_events->events |= FD_CLOSE;
- SetEvent (wsock_evt);
- break;
- case SHUT_WR:
- saw_shutdown_write (true);
- break;
- case SHUT_RDWR:
- saw_shutdown_read (true);
- saw_shutdown_write (true);
- wsock_events->events |= FD_CLOSE;
- SetEvent (wsock_evt);
- break;
- }
- }
- return res;
-}
-
-int
-fhandler_socket_local::close ()
-{
- int res = 0;
-
- release_events ();
- while ((res = ::closesocket (get_socket ())) != 0)
- {
- if (WSAGetLastError () != WSAEWOULDBLOCK)
- {
- set_winsock_errno ();
- res = -1;
- break;
- }
- if (cygwait (10) == WAIT_SIGNALED)
- {
- set_errno (EINTR);
- res = -1;
- break;
- }
- WSASetLastError (0);
- }
-
- debug_printf ("%d = fhandler_socket::close()", res);
- return res;
-}
-
-inline ssize_t
+ssize_t
fhandler_socket_local::recv_internal (LPWSAMSG wsamsg, bool use_recvmsg)
{
ssize_t res = 0;
@@ -1280,235 +1215,6 @@ fhandler_socket_local::recv_internal (LPWSAMSG wsamsg, bool use_recvmsg)
}
ssize_t
-fhandler_socket_local::recvfrom (void *in_ptr, size_t len, int flags,
- struct sockaddr *from, int *fromlen)
-{
- char *ptr = (char *) in_ptr;
-
-#ifdef __x86_64__
- /* size_t is 64 bit, but the len member in WSABUF is 32 bit.
- Split buffer if necessary. */
- DWORD bufcnt = len / UINT32_MAX + ((!len || (len % UINT32_MAX)) ? 1 : 0);
- WSABUF wsabuf[bufcnt];
- WSAMSG wsamsg = { from, from && fromlen ? *fromlen : 0,
- wsabuf, bufcnt,
- { 0, NULL },
- (DWORD) flags };
- /* Don't use len as loop condition, it could be 0. */
- for (WSABUF *wsaptr = wsabuf; bufcnt--; ++wsaptr)
- {
- wsaptr->len = MIN (len, UINT32_MAX);
- wsaptr->buf = ptr;
- len -= wsaptr->len;
- ptr += wsaptr->len;
- }
-#else
- WSABUF wsabuf = { len, ptr };
- WSAMSG wsamsg = { from, from && fromlen ? *fromlen : 0,
- &wsabuf, 1,
- { 0, NULL},
- (DWORD) flags };
-#endif
- ssize_t ret = recv_internal (&wsamsg, false);
- if (fromlen)
- *fromlen = wsamsg.namelen;
- return ret;
-}
-
-ssize_t
-fhandler_socket_local::recvmsg (struct msghdr *msg, int flags)
-{
- /* TODO: Descriptor passing on AF_LOCAL sockets. */
-
- /* Disappointing but true: Even if WSARecvMsg is supported, it's only
- supported for datagram and raw sockets. */
- bool use_recvmsg = true;
- if (get_socket_type () == SOCK_STREAM || get_addr_family () == AF_LOCAL)
- {
- use_recvmsg = false;
- msg->msg_controllen = 0;
- }
-
- WSABUF wsabuf[msg->msg_iovlen];
- WSABUF *wsaptr = wsabuf + msg->msg_iovlen;
- const struct iovec *iovptr = msg->msg_iov + msg->msg_iovlen;
- while (--wsaptr >= wsabuf)
- {
- wsaptr->len = (--iovptr)->iov_len;
- wsaptr->buf = (char *) iovptr->iov_base;
- }
- WSAMSG wsamsg = { (struct sockaddr *) msg->msg_name, msg->msg_namelen,
- wsabuf, (DWORD) msg->msg_iovlen,
- { (DWORD) msg->msg_controllen, (char *) msg->msg_control },
- (DWORD) flags };
- ssize_t ret = recv_internal (&wsamsg, use_recvmsg);
- if (ret >= 0)
- {
- msg->msg_namelen = wsamsg.namelen;
- msg->msg_controllen = wsamsg.Control.len;
- if (!CYGWIN_VERSION_CHECK_FOR_USING_ANCIENT_MSGHDR)
- msg->msg_flags = wsamsg.dwFlags;
- }
- return ret;
-}
-
-void __reg3
-fhandler_socket_local::read (void *in_ptr, size_t& len)
-{
- char *ptr = (char *) in_ptr;
-
-#ifdef __x86_64__
- /* size_t is 64 bit, but the len member in WSABUF is 32 bit.
- Split buffer if necessary. */
- DWORD bufcnt = len / UINT32_MAX + ((!len || (len % UINT32_MAX)) ? 1 : 0);
- WSABUF wsabuf[bufcnt];
- WSAMSG wsamsg = { NULL, 0, wsabuf, bufcnt, { 0, NULL }, 0 };
- /* Don't use len as loop condition, it could be 0. */
- for (WSABUF *wsaptr = wsabuf; bufcnt--; ++wsaptr)
- {
- wsaptr->len = MIN (len, UINT32_MAX);
- wsaptr->buf = ptr;
- len -= wsaptr->len;
- ptr += wsaptr->len;
- }
-#else
- WSABUF wsabuf = { len, ptr };
- WSAMSG wsamsg = { NULL, 0, &wsabuf, 1, { 0, NULL }, 0 };
-#endif
-
- len = recv_internal (&wsamsg, false);
-}
-
-ssize_t
-fhandler_socket_local::readv (const struct iovec *const iov, const int iovcnt,
- ssize_t tot)
-{
- WSABUF wsabuf[iovcnt];
- WSABUF *wsaptr = wsabuf + iovcnt;
- const struct iovec *iovptr = iov + iovcnt;
- while (--wsaptr >= wsabuf)
- {
- wsaptr->len = (--iovptr)->iov_len;
- wsaptr->buf = (char *) iovptr->iov_base;
- }
- WSAMSG wsamsg = { NULL, 0, wsabuf, (DWORD) iovcnt, { 0, NULL}, 0 };
- return recv_internal (&wsamsg, false);
-}
-
-inline ssize_t
-fhandler_socket_local::send_internal (struct _WSAMSG *wsamsg, int flags)
-{
- ssize_t res = 0;
- DWORD ret = 0, sum = 0;
- WSABUF out_buf[wsamsg->dwBufferCount];
- bool use_sendmsg = false;
- DWORD wait_flags = flags & MSG_DONTWAIT;
- bool nosignal = !!(flags & MSG_NOSIGNAL);
-
- flags &= (MSG_OOB | MSG_DONTROUTE);
- if (wsamsg->Control.len > 0)
- use_sendmsg = true;
- /* Workaround for MSDN KB 823764: Split a message into chunks <= SO_SNDBUF.
- in_idx is the index of the current lpBuffers from the input wsamsg buffer.
- in_off is used to keep track of the next byte to write from a wsamsg
- buffer which only gets partially written. */
- for (DWORD in_idx = 0, in_off = 0;
- in_idx < wsamsg->dwBufferCount;
- in_off >= wsamsg->lpBuffers[in_idx].len && (++in_idx, in_off = 0))
- {
- /* Split a message into the least number of pieces to minimize the
- number of WsaSendTo calls. Don't split datagram messages (bad idea).
- out_idx is the index of the next buffer in the out_buf WSABUF,
- also the number of buffers given to WSASendTo.
- out_len is the number of bytes in the buffers given to WSASendTo.
- Don't split datagram messages (very bad idea). */
- DWORD out_idx = 0;
- DWORD out_len = 0;
- if (get_socket_type () == SOCK_STREAM)
- {
- do
- {
- out_buf[out_idx].buf = wsamsg->lpBuffers[in_idx].buf + in_off;
- out_buf[out_idx].len = wsamsg->lpBuffers[in_idx].len - in_off;
- out_len += out_buf[out_idx].len;
- out_idx++;
- }
- while (out_len < (unsigned) wmem ()
- && (in_off = 0, ++in_idx < wsamsg->dwBufferCount));
- /* Tweak len of the last out_buf buffer so the entire number of bytes
- is (less than or) equal to wmem (). Fix out_len as well since it's
- used in a subsequent test expression. */
- if (out_len > (unsigned) wmem ())
- {
- out_buf[out_idx - 1].len -= out_len - (unsigned) wmem ();
- out_len = (unsigned) wmem ();
- }
- /* Add the bytes written from the current last buffer to in_off,
- so in_off points to the next byte to be written from that buffer,
- or beyond which lets the outper loop skip to the next buffer. */
- in_off += out_buf[out_idx - 1].len;
- }
-
- do
- {
- if (use_sendmsg)
- res = WSASendMsg (get_socket (), wsamsg, flags, &ret, NULL, NULL);
- else if (get_socket_type () == SOCK_STREAM)
- res = WSASendTo (get_socket (), out_buf, out_idx, &ret, flags,
- wsamsg->name, wsamsg->namelen, NULL, NULL);
- else
- res = WSASendTo (get_socket (), wsamsg->lpBuffers,
- wsamsg->dwBufferCount, &ret, flags,
- wsamsg->name, wsamsg->namelen, NULL, NULL);
- if (res && (WSAGetLastError () == WSAEWOULDBLOCK))
- {
- LOCK_EVENTS;
- wsock_events->events &= ~FD_WRITE;
- UNLOCK_EVENTS;
- }
- }
- while (res && (WSAGetLastError () == WSAEWOULDBLOCK)
- && !(res = wait_for_events (FD_WRITE | FD_CLOSE, wait_flags)));
-
- if (!res)
- {
- sum += ret;
- /* For streams, return to application if the number of bytes written
- is less than the number of bytes we intended to write in a single
- call to WSASendTo. Otherwise we would have to add code to
- backtrack in the input buffers, which is questionable. There was
- probably a good reason we couldn't write more. */
- if (get_socket_type () != SOCK_STREAM || ret < out_len)
- break;
- }
- else if (is_nonblocking () || WSAGetLastError() != WSAEWOULDBLOCK)
- break;
- }
-
- if (sum)
- res = sum;
- else if (res == SOCKET_ERROR)
- {
- set_winsock_errno ();
-
- /* Special handling for EPIPE and SIGPIPE.
-
- EPIPE is generated if the local end has been shut down on a connection
- oriented socket. In this case the process will also receive a SIGPIPE
- unless MSG_NOSIGNAL is set. */
- if ((get_errno () == ECONNABORTED || get_errno () == ESHUTDOWN)
- && get_socket_type () == SOCK_STREAM)
- {
- set_errno (EPIPE);
- if (!nosignal)
- raise (SIGPIPE);
- }
- }
-
- return res;
-}
-
-ssize_t
fhandler_socket_local::sendto (const void *in_ptr, size_t len, int flags,
const struct sockaddr *to, int tolen)
{
@@ -1578,48 +1284,6 @@ fhandler_socket_local::sendmsg (const struct msghdr *msg, int flags)
return send_internal (&wsamsg, flags);
}
-ssize_t
-fhandler_socket_local::write (const void *in_ptr, size_t len)
-{
- char *ptr = (char *) in_ptr;
-
-#ifdef __x86_64__
- /* size_t is 64 bit, but the len member in WSABUF is 32 bit.
- Split buffer if necessary. */
- DWORD bufcnt = len / UINT32_MAX + ((!len || (len % UINT32_MAX)) ? 1 : 0);
- WSABUF wsabuf[bufcnt];
- WSAMSG wsamsg = { NULL, 0, wsabuf, bufcnt, { 0, NULL }, 0 };
- /* Don't use len as loop condition, it could be 0. */
- for (WSABUF *wsaptr = wsabuf; bufcnt--; ++wsaptr)
- {
- wsaptr->len = MIN (len, UINT32_MAX);
- wsaptr->buf = ptr;
- len -= wsaptr->len;
- ptr += wsaptr->len;
- }
-#else
- WSABUF wsabuf = { len, ptr };
- WSAMSG wsamsg = { NULL, 0, &wsabuf, 1, { 0, NULL }, 0 };
-#endif
- return send_internal (&wsamsg, 0);
-}
-
-ssize_t
-fhandler_socket_local::writev (const struct iovec *const iov, const int iovcnt,
- ssize_t tot)
-{
- WSABUF wsabuf[iovcnt];
- WSABUF *wsaptr = wsabuf;
- const struct iovec *iovptr = iov;
- for (int i = 0; i < iovcnt; ++i)
- {
- wsaptr->len = iovptr->iov_len;
- (wsaptr++)->buf = (char *) (iovptr++)->iov_base;
- }
- WSAMSG wsamsg = { NULL, 0, wsabuf, (DWORD) iovcnt, { 0, NULL}, 0 };
- return send_internal (&wsamsg, 0);
-}
-
void
fhandler_socket_local::set_sun_path (const char *path)
{
@@ -1907,86 +1571,3 @@ fhandler_socket_local::getsockopt (int level, int optname, const void *optval,
return ret;
}
-
-int
-fhandler_socket_local::ioctl (unsigned int cmd, void *p)
-{
- int res;
-
- switch (cmd)
- {
- /* FIXME: These have to be handled differently in future. */
- case FIOASYNC:
-#ifdef __x86_64__
- case _IOW('f', 125, u_long):
-#endif
- res = WSAAsyncSelect (get_socket (), winmsg, WM_ASYNCIO,
- *(int *) p ? ASYNC_MASK : 0);
- syscall_printf ("Async I/O on socket %s",
- *(int *) p ? "started" : "cancelled");
- async_io (*(int *) p != 0);
- /* If async_io is switched off, revert the event handling. */
- if (*(int *) p == 0)
- WSAEventSelect (get_socket (), wsock_evt, EVENT_MASK);
- break;
- case FIONREAD:
-#ifdef __x86_64__
- case _IOR('f', 127, u_long):
-#endif
- /* Make sure to use the Winsock definition of FIONREAD. */
- res = ::ioctlsocket (get_socket (), _IOR('f', 127, u_long), (u_long *) p);
- if (res == SOCKET_ERROR)
- set_winsock_errno ();
- break;
- case FIONBIO:
- case SIOCATMARK:
- /* Sockets are always non-blocking internally. So we just note the
- state here. */
-#ifdef __x86_64__
- /* Convert the different idea of u_long in the definition of cmd. */
- if (((cmd >> 16) & IOCPARM_MASK) == sizeof (unsigned long))
- cmd = (cmd & ~(IOCPARM_MASK << 16)) | (sizeof (u_long) << 16);
-#endif
- if (cmd == FIONBIO)
- {
- syscall_printf ("socket is now %sblocking",
- *(int *) p ? "non" : "");
- set_nonblocking (*(int *) p);
- res = 0;
- }
- else
- res = ::ioctlsocket (get_socket (), cmd, (u_long *) p);
- break;
- default:
- res = fhandler_socket::ioctl (cmd, p);
- break;
- }
- syscall_printf ("%d = ioctl_socket(%x, %p)", res, cmd, p);
- return res;
-}
-
-int
-fhandler_socket_local::fcntl (int cmd, intptr_t arg)
-{
- int res = 0;
-
- switch (cmd)
- {
- case F_SETOWN:
- {
- pid_t pid = (pid_t) arg;
- LOCK_EVENTS;
- wsock_events->owner = pid;
- UNLOCK_EVENTS;
- debug_printf ("owner set to %d", pid);
- }
- break;
- case F_GETOWN:
- res = wsock_events->owner;
- break;
- default:
- res = fhandler_socket::fcntl (cmd, arg);
- break;
- }
- return res;
-}
diff --git a/winsup/cygwin/net.cc b/winsup/cygwin/net.cc
index 6b88f9105..fe6576dc9 100644
--- a/winsup/cygwin/net.cc
+++ b/winsup/cygwin/net.cc
@@ -1384,8 +1384,7 @@ cygwin_getpeername (int fd, struct sockaddr *name, socklen_t *len)
}
__except (EFAULT) {}
__endtry
- syscall_printf ("%R = getpeername(%d) %p", res, fd,
- (fh ? fh->get_socket () : (SOCKET) -1));
+ syscall_printf ("%R = getpeername(%d)", res, fd);
return res;
}
diff --git a/winsup/cygwin/poll.cc b/winsup/cygwin/poll.cc
index ea45b70ad..440413433 100644
--- a/winsup/cygwin/poll.cc
+++ b/winsup/cygwin/poll.cc
@@ -94,12 +94,12 @@ poll (struct pollfd *fds, nfds_t nfds, int timeout)
{
if (fds[i].fd >= 0 && fds[i].revents != POLLNVAL)
{
- fhandler_socket *sock;
+ fhandler_socket_wsock *sock;
/* Check if the descriptor has been closed, or if shutdown for the
read side has been called on a socket. */
if (cygheap->fdtab.not_open (fds[i].fd)
- || ((sock = cygheap->fdtab[fds[i].fd]->is_socket ())
+ || ((sock = cygheap->fdtab[fds[i].fd]->is_wsock_socket ())
&& sock->saw_shutdown_read ()))
fds[i].revents = POLLHUP;
else
@@ -117,7 +117,7 @@ poll (struct pollfd *fds, nfds_t nfds, int timeout)
/* Handle failed connect. A failed connect implicitly sets
POLLOUT, if requested, but it doesn't set POLLIN. */
if ((fds[i].events & POLLIN)
- && (sock = cygheap->fdtab[fds[i].fd]->is_socket ())
+ && (sock = cygheap->fdtab[fds[i].fd]->is_wsock_socket ())
&& sock->connect_state () == connect_failed)
fds[i].revents |= (POLLIN | POLLERR);
else
diff --git a/winsup/cygwin/select.cc b/winsup/cygwin/select.cc
index 86e7cd8fd..023bec048 100644
--- a/winsup/cygwin/select.cc
+++ b/winsup/cygwin/select.cc
@@ -501,7 +501,7 @@ set_bits (select_record *me, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds)
{
int ready = 0;
- fhandler_socket *sock;
+ fhandler_socket_wsock *sock;
select_printf ("me %p, testing fd %d (%s)", me, me->fd, me->fh->get_name ());
if (me->read_selected && me->read_ready)
{
@@ -511,7 +511,7 @@ set_bits (select_record *me, fd_set *readfds, fd_set *writefds,
if (me->write_selected && me->write_ready)
{
UNIX_FD_SET (me->fd, writefds);
- if (me->except_on_write && (sock = me->fh->is_socket ()))
+ if (me->except_on_write && (sock = me->fh->is_wsock_socket ()))
{
/* Set readfds entry in case of a failed connect. */
if (!me->read_ready && me->read_selected
@@ -1364,7 +1364,7 @@ fhandler_base::select_except (select_stuff *ss)
static int
peek_socket (select_record *me, bool)
{
- fhandler_socket *fh = (fhandler_socket *) me->fh;
+ fhandler_socket_wsock *fh = (fhandler_socket_wsock *) me->fh;
long events;
/* Don't play with the settings again, unless having taken a deep look into
Richard W. Stevens Network Programming book. Thank you. */
@@ -1488,7 +1488,7 @@ start_thread_socket (select_record *me, select_stuff *stuff)
/* No event/socket should show up multiple times. Every socket
is uniquely identified by its serial number in the global
wsock_events record. */
- const LONG ser_num = ((fhandler_socket *) s->fh)->serial_number ();
+ const LONG ser_num = ((fhandler_socket_wsock *) s->fh)->serial_number ();
for (int i = 1; i < si->num_w4; ++i)
if (si->ser_num[i] == ser_num)
goto continue_outer_loop;
@@ -1517,7 +1517,7 @@ start_thread_socket (select_record *me, select_stuff *stuff)
_my_tls.locals.select.max_w4 += MAXIMUM_WAIT_OBJECTS;
}
si->ser_num[si->num_w4] = ser_num;
- si->w4[si->num_w4++] = ((fhandler_socket *) s->fh)->wsock_event ();
+ si->w4[si->num_w4++] = ((fhandler_socket_wsock *) s->fh)->wsock_event ();
continue_outer_loop:
;
}
@@ -1549,7 +1549,7 @@ socket_cleanup (select_record *, select_stuff *stuff)
}
select_record *
-fhandler_socket_inet::select_read (select_stuff *ss)
+fhandler_socket_wsock::select_read (select_stuff *ss)
{
select_record *s = ss->start.next;
if (!s->startup)
@@ -1565,7 +1565,7 @@ fhandler_socket_inet::select_read (select_stuff *ss)
}
select_record *
-fhandler_socket_inet::select_write (select_stuff *ss)
+fhandler_socket_wsock::select_write (select_stuff *ss)
{
select_record *s = ss->start.next;
if (!s->startup)
@@ -1586,61 +1586,7 @@ fhandler_socket_inet::select_write (select_stuff *ss)
}
select_record *
-fhandler_socket_inet::select_except (select_stuff *ss)
-{
- select_record *s = ss->start.next;
- if (!s->startup)
- {
- s->startup = start_thread_socket;
- s->verify = verify_true;
- s->cleanup = socket_cleanup;
- }
- s->peek = peek_socket;
- /* FIXME: Is this right? Should these be used as criteria for except? */
- s->except_ready = saw_shutdown_write () || saw_shutdown_read ();
- s->except_selected = true;
- return s;
-}
-
-select_record *
-fhandler_socket_local::select_read (select_stuff *ss)
-{
- select_record *s = ss->start.next;
- if (!s->startup)
- {
- s->startup = start_thread_socket;
- s->verify = verify_true;
- s->cleanup = socket_cleanup;
- }
- s->peek = peek_socket;
- s->read_ready = saw_shutdown_read ();
- s->read_selected = true;
- return s;
-}
-
-select_record *
-fhandler_socket_local::select_write (select_stuff *ss)
-{
- select_record *s = ss->start.next;
- if (!s->startup)
- {
- s->startup = start_thread_socket;
- s->verify = verify_true;
- s->cleanup = socket_cleanup;
- }
- s->peek = peek_socket;
- s->write_ready = saw_shutdown_write () || connect_state () == unconnected;
- s->write_selected = true;
- if (connect_state () != unconnected)
- {
- s->except_ready = saw_shutdown_write () || saw_shutdown_read ();
- s->except_on_write = true;
- }
- return s;
-}
-
-select_record *
-fhandler_socket_local::select_except (select_stuff *ss)
+fhandler_socket_wsock::select_except (select_stuff *ss)
{
select_record *s = ss->start.next;
if (!s->startup)