Cygwin: FIFO: add a spinlock
Don't let listen_client_thread and raw_read access the client list simultaneously.
This commit is contained in:
parent
48d4cce3be
commit
c75e077f99
@ -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 ();
|
||||
|
@ -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)
|
||||
{
|
||||
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)
|
||||
res = add_client ();
|
||||
fifo_client_unlock ();
|
||||
if (res < 0)
|
||||
goto errout;
|
||||
else
|
||||
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)
|
||||
{
|
||||
fifo_client_unlock ();
|
||||
return;
|
||||
}
|
||||
else if (nread < 0 && GetLastError () != ERROR_NO_DATA)
|
||||
{
|
||||
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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user