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];
|
WCHAR pipe_name_buf[CYGWIN_FIFO_PIPE_NAME_LEN + 1];
|
||||||
fifo_client_handler client[MAX_CLIENTS];
|
fifo_client_handler client[MAX_CLIENTS];
|
||||||
int nclients, nconnected;
|
int nclients, nconnected;
|
||||||
|
af_unix_spinlock_t _fifo_client_lock;
|
||||||
bool __reg2 wait (HANDLE);
|
bool __reg2 wait (HANDLE);
|
||||||
NTSTATUS npfs_handle (HANDLE &);
|
NTSTATUS npfs_handle (HANDLE &);
|
||||||
HANDLE create_pipe_instance (bool);
|
HANDLE create_pipe_instance (bool);
|
||||||
@ -1278,6 +1279,8 @@ public:
|
|||||||
fhandler_fifo ();
|
fhandler_fifo ();
|
||||||
PUNICODE_STRING get_pipe_name ();
|
PUNICODE_STRING get_pipe_name ();
|
||||||
DWORD listen_client_thread ();
|
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);
|
int open (int, mode_t);
|
||||||
off_t lseek (off_t offset, int whence);
|
off_t lseek (off_t offset, int whence);
|
||||||
int close ();
|
int close ();
|
||||||
|
@ -349,13 +349,17 @@ fhandler_fifo::listen_client_thread ()
|
|||||||
int i;
|
int i;
|
||||||
DWORD wait_ret;
|
DWORD wait_ret;
|
||||||
|
|
||||||
|
fifo_client_lock ();
|
||||||
found = false;
|
found = false;
|
||||||
for (i = 0; i < nclients; i++)
|
for (i = 0; i < nclients; i++)
|
||||||
switch (client[i].state)
|
switch (client[i].state)
|
||||||
{
|
{
|
||||||
case fc_invalid:
|
case fc_invalid:
|
||||||
if (disconnect_and_reconnect (i) < 0)
|
if (disconnect_and_reconnect (i) < 0)
|
||||||
goto errout;
|
{
|
||||||
|
fifo_client_unlock ();
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
/* Fall through. */
|
/* Fall through. */
|
||||||
case fc_connected:
|
case fc_connected:
|
||||||
w[i] = client[i].dummy_evt;
|
w[i] = client[i].dummy_evt;
|
||||||
@ -369,13 +373,15 @@ fhandler_fifo::listen_client_thread ()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
w[nclients] = lct_termination_evt;
|
w[nclients] = lct_termination_evt;
|
||||||
|
int res = 0;
|
||||||
if (!found)
|
if (!found)
|
||||||
{
|
res = add_client ();
|
||||||
if (add_client () < 0)
|
fifo_client_unlock ();
|
||||||
goto errout;
|
if (res < 0)
|
||||||
else
|
goto errout;
|
||||||
continue;
|
else if (!found)
|
||||||
}
|
continue;
|
||||||
|
|
||||||
if (!arm (read_ready))
|
if (!arm (read_ready))
|
||||||
{
|
{
|
||||||
__seterrno ();
|
__seterrno ();
|
||||||
@ -391,9 +397,11 @@ fhandler_fifo::listen_client_thread ()
|
|||||||
return 0;
|
return 0;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
fifo_client_lock ();
|
||||||
client[i].state = fc_connected;
|
client[i].state = fc_connected;
|
||||||
nconnected++;
|
nconnected++;
|
||||||
set_pipe_non_blocking (client[i].fh->get_handle (), true);
|
set_pipe_non_blocking (client[i].fh->get_handle (), true);
|
||||||
|
fifo_client_unlock ();
|
||||||
yield ();
|
yield ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -664,6 +672,7 @@ fhandler_fifo::raw_read (void *in_ptr, size_t& len)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Poll the connected clients for input. */
|
/* Poll the connected clients for input. */
|
||||||
|
fifo_client_lock ();
|
||||||
for (int i = 0; i < nclients; i++)
|
for (int i = 0; i < nclients; i++)
|
||||||
if (client[i].state == fc_connected)
|
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);
|
client[i].fh->fhandler_base::raw_read (in_ptr, len);
|
||||||
ssize_t nread = (ssize_t) len;
|
ssize_t nread = (ssize_t) len;
|
||||||
if (nread > 0)
|
if (nread > 0)
|
||||||
return;
|
{
|
||||||
|
fifo_client_unlock ();
|
||||||
|
return;
|
||||||
|
}
|
||||||
else if (nread < 0 && GetLastError () != ERROR_NO_DATA)
|
else if (nread < 0 && GetLastError () != ERROR_NO_DATA)
|
||||||
goto errout;
|
{
|
||||||
|
fifo_client_unlock ();
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
else if (nread == 0) /* Client has disconnected. */
|
else if (nread == 0) /* Client has disconnected. */
|
||||||
{
|
{
|
||||||
client[i].state = fc_invalid;
|
client[i].state = fc_invalid;
|
||||||
nconnected--;
|
nconnected--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fifo_client_unlock ();
|
||||||
if (is_nonblocking ())
|
if (is_nonblocking ())
|
||||||
{
|
{
|
||||||
set_errno (EAGAIN);
|
set_errno (EAGAIN);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user