Cygwin: FIFO: allow take_ownership to be interrupted

Use cygwait in take_ownership to allow interruption while waiting to
become owner.  Return the cygwait return value or a suitable value to
indicate an error.

raw_read now checks the return value and acts accordingly.
This commit is contained in:
Ken Brown 2020-07-13 07:01:57 -04:00
parent a4dc0eb15c
commit 4eaa55463d
3 changed files with 59 additions and 8 deletions

View File

@ -1489,7 +1489,7 @@ public:
void owner_lock () { shmem->owner_lock (); }
void owner_unlock () { shmem->owner_unlock (); }
void take_ownership ();
DWORD take_ownership ();
void reading_lock () { shmem->reading_lock (); }
void reading_unlock () { shmem->reading_unlock (); }

View File

@ -1175,15 +1175,16 @@ fhandler_fifo::raw_write (const void *ptr, size_t len)
return ret;
}
/* Called from raw_read and select.cc:peek_fifo. */
void
/* Called from raw_read and select.cc:peek_fifo. Return WAIT_OBJECT_0
on success. */
DWORD
fhandler_fifo::take_ownership ()
{
owner_lock ();
if (get_owner () == me)
{
owner_unlock ();
return;
return WAIT_OBJECT_0;
}
set_pending_owner (me);
/* Wake up my fifo_reader_thread. */
@ -1192,8 +1193,19 @@ fhandler_fifo::take_ownership ()
/* Wake up owner's fifo_reader_thread. */
SetEvent (update_needed_evt);
owner_unlock ();
/* The reader threads should now do the transfer. */
WaitForSingleObject (owner_found_evt, INFINITE);
/* The reader threads should now do the transfer. */
DWORD waitret = cygwait (owner_found_evt, cw_cancel | cw_sig_eintr);
owner_lock ();
if (waitret == WAIT_OBJECT_0
&& (get_owner () != me || get_pending_owner ()))
{
/* Something went wrong. Return WAIT_TIMEOUT, which can't be
returned by the above cygwait call. */
set_pending_owner (null_fr_id);
waitret = WAIT_TIMEOUT;
}
owner_unlock ();
return waitret;
}
void __reg3
@ -1206,7 +1218,37 @@ fhandler_fifo::raw_read (void *in_ptr, size_t& len)
{
/* No one else can take ownership while we hold the reading_lock. */
reading_lock ();
take_ownership ();
switch (take_ownership ())
{
case WAIT_OBJECT_0:
break;
case WAIT_SIGNALED:
if (_my_tls.call_signal_handler ())
{
reading_unlock ();
continue;
}
else
{
set_errno (EINTR);
reading_unlock ();
goto errout;
}
break;
case WAIT_CANCELED:
reading_unlock ();
pthread::static_cancel_self ();
break;
case WAIT_TIMEOUT:
reading_unlock ();
debug_printf ("take_ownership returned an unexpected result; retry");
continue;
default:
reading_unlock ();
debug_printf ("unknown error while trying to take ownership, %E");
goto errout;
}
/* Poll the connected clients for input. Make two passes. On
the first pass, just try to read from the client from which
we last read successfully. This should minimize

View File

@ -867,7 +867,16 @@ peek_fifo (select_record *s, bool from_select)
}
fh->reading_lock ();
fh->take_ownership ();
if (fh->take_ownership () != WAIT_OBJECT_0)
{
select_printf ("%s, unable to take ownership", fh->get_name ());
fh->reading_unlock ();
gotone += s->read_ready = true;
if (s->except_selected)
gotone += s->except_ready = true;
goto out;
}
fh->fifo_client_lock ();
int nconnected = 0;
for (int i = 0; i < fh->get_nhandlers (); i++)