From cadfa90a5e50bfbf2251ce753e251332884e6fa3 Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Fri, 21 Jul 2006 09:47:46 +0000 Subject: * fhandler.h (class fhandler_socket): Rearrange slightly to keep event handling methods and members together. Drop owner status flag. Split wait method. Rename event handling methods for readability. * fhandler_socket.cc (struct wsa_event): Add owner field. (LOCK_EVENTS): New macro. (UNLOCK_EVENTS): Ditto. (fhandler_socket::init_events): rename from prepare. (fhandler_socket::evaluate_events): First half of former wait method. Do everything but wait. Allow specifiying whether or not events from event_mask should be erased from wsock_events->events. Simplify OOB handling. Allow sending SIGURG to any process (group). (fhandler_socket::wait_for_events): Second half of former wait method. Call evaluate_events and wait in a loop if socket is blocking. (fhandler_socket::release_events): Rename from release. (fhandler_socket::connect): Accomodate above name changes. (fhandler_socket::accept): Ditto. (fhandler_socket::recv_internal): Ditto. (fhandler_socket::send_internal): Ditto. (fhandler_socket::close): Ditto. (fhandler_socket::fcntl): Always set owner to given input value on F_SETOWN. Handle F_GETOWN. * net.cc (fdsock): Accomodate above name changes. --- winsup/cygwin/ChangeLog | 25 ++++++++ winsup/cygwin/fhandler.h | 16 +++-- winsup/cygwin/fhandler_socket.cc | 130 +++++++++++++++++++-------------------- winsup/cygwin/net.cc | 2 +- 4 files changed, 97 insertions(+), 76 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 3284601ff99..b53417d7e6e 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,28 @@ +2006-07-20 Corinna Vinschen + + * fhandler.h (class fhandler_socket): Rearrange slightly to keep + event handling methods and members together. Drop owner status flag. + Split wait method. Rename event handling methods for readability. + * fhandler_socket.cc (struct wsa_event): Add owner field. + (LOCK_EVENTS): New macro. + (UNLOCK_EVENTS): Ditto. + (fhandler_socket::init_events): rename from prepare. + (fhandler_socket::evaluate_events): First half of former wait method. + Do everything but wait. Allow specifiying whether or not events from + event_mask should be erased from wsock_events->events. Simplify + OOB handling. Allow sending SIGURG to any process (group). + (fhandler_socket::wait_for_events): Second half of former wait method. + Call evaluate_events and wait in a loop if socket is blocking. + (fhandler_socket::release_events): Rename from release. + (fhandler_socket::connect): Accomodate above name changes. + (fhandler_socket::accept): Ditto. + (fhandler_socket::recv_internal): Ditto. + (fhandler_socket::send_internal): Ditto. + (fhandler_socket::close): Ditto. + (fhandler_socket::fcntl): Always set owner to given input value on + F_SETOWN. Handle F_GETOWN. + * net.cc (fdsock): Accomodate above name changes. + 2006-07-20 Corinna Vinschen * fhandler_socket.cc (fhandler_socket::wait): Set Winsock errno to diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h index 06ae26e01a2..afcd6db5f25 100644 --- a/winsup/cygwin/fhandler.h +++ b/winsup/cygwin/fhandler.h @@ -390,6 +390,12 @@ class fhandler_socket: public fhandler_base HANDLE wsock_mtx; HANDLE wsock_evt; wsa_event *wsock_events; + public: + bool init_events (); + private: + int evaluate_events (const long event_mask, long &events, bool erase); + int wait_for_events (const long event_mask); + void release_events (); pid_t sec_pid; __uid32_t sec_uid; @@ -420,22 +426,15 @@ class fhandler_socket: public fhandler_base 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 owner : 1; /* fcntl(F_SETOWN) called */ unsigned listener : 1; /* listen called */ unsigned connect_state : 2; public: status_flags () : async_io (0), saw_shutdown_read (0), saw_shutdown_write (0), - owner (0), listener (0), connect_state (unconnected) + listener (0), connect_state (unconnected) {} } status; - public: - bool prepare (); - private: - int wait (long event_mask); - void release (); - public: fhandler_socket (); ~fhandler_socket (); @@ -446,7 +445,6 @@ class fhandler_socket: public fhandler_base IMPLEMENT_STATUS_FLAG (bool, saw_shutdown_read) IMPLEMENT_STATUS_FLAG (bool, saw_shutdown_write) IMPLEMENT_STATUS_FLAG (bool, saw_reuseaddr) - IMPLEMENT_STATUS_FLAG (bool, owner) IMPLEMENT_STATUS_FLAG (bool, listener) IMPLEMENT_STATUS_FLAG (conn_state, connect_state) diff --git a/winsup/cygwin/fhandler_socket.cc b/winsup/cygwin/fhandler_socket.cc index 50b312f373c..f20ee09fdd8 100644 --- a/winsup/cygwin/fhandler_socket.cc +++ b/winsup/cygwin/fhandler_socket.cc @@ -400,6 +400,7 @@ struct wsa_event LONG serial_number; long events; int connect_errorcode; + pid_t owner; }; /* Maximum number of concurrently opened sockets from all Cygwin processes @@ -407,6 +408,9 @@ struct wsa_event counted as one socket. */ #define NUM_SOCKS (65536 / sizeof (wsa_event)) +#define LOCK_EVENTS WaitForSingleObject (wsock_mtx, INFINITE) +#define UNLOCK_EVENTS ReleaseMutex (wsock_mtx) + static wsa_event wsa_events[NUM_SOCKS] __attribute__((section (".cygwin_dll_common"), shared)) = { 0 }; static LONG socket_serial_number __attribute__((section (".cygwin_dll_common"), shared)) = 0; @@ -458,7 +462,7 @@ search_wsa_event_slot (LONG new_serial_number) } bool -fhandler_socket::prepare () +fhandler_socket::init_events () { LONG new_serial_number; char name[CYG_MAX_PATH]; @@ -504,52 +508,29 @@ fhandler_socket::prepare () } int -fhandler_socket::wait (long event_mask) +fhandler_socket::evaluate_events (const long event_mask, long &events, + bool erase) { - if (async_io ()) - return 0; - - int ret = SOCKET_ERROR; - long events; - -/* If WSAWaitForMultipleEvents is interrupted by a signal, and the signal - has the SA_RESTART flag set, return to this label and... restart. */ -sa_restart: + int ret = 0; WSANETWORKEVENTS evts = { 0 }; if (!(WSAEnumNetworkEvents (get_socket (), wsock_evt, &evts))) { if (evts.lNetworkEvents) { - WaitForSingleObject (wsock_mtx, INFINITE); + LOCK_EVENTS; wsock_events->events |= evts.lNetworkEvents; if (evts.lNetworkEvents & FD_CONNECT) wsock_events->connect_errorcode = evts.iErrorCode[FD_CONNECT_BIT]; - events = (wsock_events->events & event_mask); - ReleaseMutex (wsock_mtx); - if ((evts.lNetworkEvents & FD_OOB) - && !evts.iErrorCode[FD_OOB_BIT] - && owner ()) - { - siginfo_t si = {0}; - si.si_signo = SIGURG; - si.si_code = SI_KERNEL; - sig_send (myself_nowait, si); - if (!_my_tls.call_signal_handler () && !events) - { - WSASetLastError (WSAEINTR); - return SOCKET_ERROR; - } - sig_dispatch_pending (); - WaitForSingleObject (wsock_mtx, INFINITE); - } + UNLOCK_EVENTS; + if ((evts.lNetworkEvents & FD_OOB) && wsock_events->owner) + kill (wsock_events->owner, SIGURG); } } - WaitForSingleObject (wsock_mtx, INFINITE); + LOCK_EVENTS; if ((events = (wsock_events->events & event_mask)) != 0) { - ret = 0; if (events & FD_CONNECT) { int wsa_err = 0; @@ -560,37 +541,50 @@ sa_restart: } wsock_events->connect_errorcode = 0; } - wsock_events->events &= ~(events & ~FD_CLOSE); + if (erase) + wsock_events->events &= ~(events & ~FD_CLOSE); } - ReleaseMutex (wsock_mtx); + UNLOCK_EVENTS; - if (!events) + return ret; +} + +int +fhandler_socket::wait_for_events (const long event_mask) +{ + if (async_io ()) + return 0; + + int ret; + long events; + + while (!(ret = evaluate_events (event_mask, events, true)) && !events) { if (is_nonblocking ()) - WSASetLastError (WSAEWOULDBLOCK); - else { - WSAEVENT ev[2] = { wsock_evt, signal_arrived }; - switch (WSAWaitForMultipleEvents (2, ev, FALSE, INFINITE, FALSE)) - { - case WSA_WAIT_TIMEOUT: - WSASetLastError (WSAEWOULDBLOCK); - break; - case WSA_WAIT_EVENT_0: - goto sa_restart; - break; - case WSA_WAIT_EVENT_0 + 1: - if (_my_tls.call_signal_handler ()) - { - sig_dispatch_pending (); - goto sa_restart; - } - WSASetLastError (WSAEINTR); - break; - default: - WSASetLastError (WSAEFAULT); + WSASetLastError (WSAEWOULDBLOCK); + return SOCKET_ERROR; + } + + WSAEVENT ev[2] = { wsock_evt, signal_arrived }; + switch (WSAWaitForMultipleEvents (2, ev, FALSE, INFINITE, FALSE)) + { + case WSA_WAIT_TIMEOUT: + case WSA_WAIT_EVENT_0: + break; + + case WSA_WAIT_EVENT_0 + 1: + if (_my_tls.call_signal_handler ()) + { + sig_dispatch_pending (); break; - } + } + WSASetLastError (WSAEINTR); + return SOCKET_ERROR; + + default: + WSASetLastError (WSAEFAULT); + return SOCKET_ERROR; } } @@ -598,7 +592,7 @@ sa_restart: } void -fhandler_socket::release () +fhandler_socket::release_events () { CloseHandle (wsock_evt); CloseHandle (wsock_mtx); @@ -996,7 +990,7 @@ fhandler_socket::connect (const struct sockaddr *name, int namelen) if (!is_nonblocking () && res == SOCKET_ERROR && WSAGetLastError () == WSAEWOULDBLOCK) - res = wait (FD_CONNECT | FD_CLOSE); + res = wait_for_events (FD_CONNECT | FD_CLOSE); if (!res) err = 0; @@ -1112,7 +1106,7 @@ fhandler_socket::accept (struct sockaddr *peer, int *len) int res = 0; - while (!(res = wait (FD_ACCEPT | FD_CLOSE)) + while (!(res = wait_for_events (FD_ACCEPT | FD_CLOSE)) && (res = ::accept (get_socket (), peer, len)) == WSAEWOULDBLOCK) ; @@ -1271,7 +1265,7 @@ fhandler_socket::recv_internal (WSABUF *wsabuf, DWORD wsacnt, DWORD flags, while ((res = WSARecvFrom (get_socket (), wsabuf, wsacnt, &ret, &flags, from, fromlen, NULL, NULL)) == -1 && WSAGetLastError () == WSAEWOULDBLOCK - && !(res = wait (evt_mask))) + && !(res = wait_for_events (evt_mask))) ; } @@ -1365,7 +1359,7 @@ fhandler_socket::send_internal (struct _WSABUF *wsabuf, DWORD wsacnt, int flags, while ((res = WSASendTo (get_socket (), wsabuf, wsacnt, &ret, flags & MSG_WINMASK, to, tolen, NULL, NULL)) == -1 && WSAGetLastError () == WSAEWOULDBLOCK - && !(res = wait (FD_WRITE | FD_CLOSE))) + && !(res = wait_for_events (FD_WRITE | FD_CLOSE))) ; if (res == SOCKET_ERROR) @@ -1466,7 +1460,7 @@ fhandler_socket::close () setsockopt (get_socket (), SOL_SOCKET, SO_LINGER, (const char *)&linger, sizeof linger); - release (); + release_events (); while ((res = closesocket (get_socket ())) != 0) { if (WSAGetLastError () != WSAEWOULDBLOCK) @@ -1632,12 +1626,16 @@ fhandler_socket::fcntl (int cmd, void *arg) { case F_SETOWN: { - /* Urgh! Bad hack! */ pid_t pid = (pid_t) arg; - owner (pid == getpid ()); - debug_printf ("owner set to %d", owner ()); + LOCK_EVENTS; + wsock_events->owner = pid; + UNLOCK_EVENTS; + debug_printf ("owner set to %d", pid); } break; + case F_GETOWN: + res = wsock_events->owner; + break; case F_SETFL: { /* Carefully test for the O_NONBLOCK or deprecated OLD_O_NDELAY flag. diff --git a/winsup/cygwin/net.cc b/winsup/cygwin/net.cc index f48d2a7dc49..80f34a88612 100644 --- a/winsup/cygwin/net.cc +++ b/winsup/cygwin/net.cc @@ -513,7 +513,7 @@ fdsock (cygheap_fdmanip& fd, const device *dev, SOCKET soc) if (!fd.isopen ()) return false; fd->set_io_handle ((HANDLE) soc); - if (!((fhandler_socket *) fd)->prepare ()) + if (!((fhandler_socket *) fd)->init_events ()) return false; fd->set_flags (O_RDWR | O_BINARY); fd->uninterruptible_io (true); -- cgit v1.2.1