aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2006-07-21 09:47:46 +0000
committerCorinna Vinschen <corinna@vinschen.de>2006-07-21 09:47:46 +0000
commit2403726217c947c4c0308b0a54b832e071332539 (patch)
tree507c7755f3267936f426552dd063f85071835f33
parent791aa84049199b54b47d5fb4fd2bc51d0934b5bb (diff)
downloadnewlib-2403726217c947c4c0308b0a54b832e071332539.zip
newlib-2403726217c947c4c0308b0a54b832e071332539.tar.gz
newlib-2403726217c947c4c0308b0a54b832e071332539.tar.bz2
* 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.
-rw-r--r--winsup/cygwin/ChangeLog25
-rw-r--r--winsup/cygwin/fhandler.h16
-rw-r--r--winsup/cygwin/fhandler_socket.cc130
-rw-r--r--winsup/cygwin/net.cc2
4 files changed, 97 insertions, 76 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 3284601..b53417d 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,5 +1,30 @@
2006-07-20 Corinna Vinschen <corinna@vinschen.de>
+ * 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 <corinna@vinschen.de>
+
* fhandler_socket.cc (fhandler_socket::wait): Set Winsock errno to
WSAEWOULDBLOCK instead of WSAEINPROGRESS.
diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index 06ae26e..afcd6db 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,23 +426,16 @@ 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 ();
int get_socket () { return (int) get_handle(); }
@@ -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 50b312f..f20ee09 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 f48d2a7..80f34a8 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);