[newlib-cygwin] Cygwin: FIFO: add a spinlock
Corinna Vinschen
corinna@sourceware.org
Wed Mar 27 13:02:00 GMT 2019
https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=c75e077f9953e3ecc6ba371d7ef95e14883a68ba
commit c75e077f9953e3ecc6ba371d7ef95e14883a68ba
Author: Ken Brown <kbrown@cornell.edu>
Date: Fri Mar 22 19:30:38 2019 +0000
Cygwin: FIFO: add a spinlock
Don't let listen_client_thread and raw_read access the client list
simultaneously.
Diff:
---
winsup/cygwin/fhandler.h | 3 +++
winsup/cygwin/fhandler_fifo.cc | 34 +++++++++++++++++++++++++---------
2 files changed, 28 insertions(+), 9 deletions(-)
diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index e7c4af6..997dc0b 100644
--- a/winsup/cygwin/fhandler.h
+++ b/winsup/cygwin/fhandler.h
@@ -1267,6 +1267,7 @@ class fhandler_fifo: public fhandler_base
WCHAR pipe_name_buf[CYGWIN_FIFO_PIPE_NAME_LEN + 1];
fifo_client_handler client[MAX_CLIENTS];
int nclients, nconnected;
+ af_unix_spinlock_t _fifo_client_lock;
bool __reg2 wait (HANDLE);
NTSTATUS npfs_handle (HANDLE &);
HANDLE create_pipe_instance (bool);
@@ -1278,6 +1279,8 @@ public:
fhandler_fifo ();
PUNICODE_STRING get_pipe_name ();
DWORD listen_client_thread ();
+ void fifo_client_lock () { _fifo_client_lock.lock (); }
+ void fifo_client_unlock () { _fifo_client_lock.unlock (); }
int open (int, mode_t);
off_t lseek (off_t offset, int whence);
int close ();
diff --git a/winsup/cygwin/fhandler_fifo.cc b/winsup/cygwin/fhandler_fifo.cc
index e91e880..b0016ee 100644
--- a/winsup/cygwin/fhandler_fifo.cc
+++ b/winsup/cygwin/fhandler_fifo.cc
@@ -349,13 +349,17 @@ fhandler_fifo::listen_client_thread ()
int i;
DWORD wait_ret;
+ fifo_client_lock ();
found = false;
for (i = 0; i < nclients; i++)
switch (client[i].state)
{
case fc_invalid:
if (disconnect_and_reconnect (i) < 0)
- goto errout;
+ {
+ fifo_client_unlock ();
+ goto errout;
+ }
/* Fall through. */
case fc_connected:
w[i] = client[i].dummy_evt;
@@ -369,13 +373,15 @@ fhandler_fifo::listen_client_thread ()
break;
}
w[nclients] = lct_termination_evt;
+ int res = 0;
if (!found)
- {
- if (add_client () < 0)
- goto errout;
- else
- continue;
- }
+ res = add_client ();
+ fifo_client_unlock ();
+ if (res < 0)
+ goto errout;
+ else if (!found)
+ continue;
+
if (!arm (read_ready))
{
__seterrno ();
@@ -391,9 +397,11 @@ fhandler_fifo::listen_client_thread ()
return 0;
else
{
+ fifo_client_lock ();
client[i].state = fc_connected;
nconnected++;
set_pipe_non_blocking (client[i].fh->get_handle (), true);
+ fifo_client_unlock ();
yield ();
}
}
@@ -664,6 +672,7 @@ fhandler_fifo::raw_read (void *in_ptr, size_t& len)
}
/* Poll the connected clients for input. */
+ fifo_client_lock ();
for (int i = 0; i < nclients; i++)
if (client[i].state == fc_connected)
{
@@ -671,15 +680,22 @@ fhandler_fifo::raw_read (void *in_ptr, size_t& len)
client[i].fh->fhandler_base::raw_read (in_ptr, len);
ssize_t nread = (ssize_t) len;
if (nread > 0)
- return;
+ {
+ fifo_client_unlock ();
+ return;
+ }
else if (nread < 0 && GetLastError () != ERROR_NO_DATA)
- goto errout;
+ {
+ fifo_client_unlock ();
+ goto errout;
+ }
else if (nread == 0) /* Client has disconnected. */
{
client[i].state = fc_invalid;
nconnected--;
}
}
+ fifo_client_unlock ();
if (is_nonblocking ())
{
set_errno (EAGAIN);
More information about the Cygwin-cvs
mailing list