Cygwin: fhandler_fifo::raw_read: handle STATUS_PENDING
NtReadFile can return STATUS_PENDING occasionally even in non-blocking mode. Check for this and wait for NtReadFile to complete. To avoid code repetition, do this in a static helper function nt_read.
This commit is contained in:
parent
6d34b62cb8
commit
4f47e64b11
|
@ -1201,12 +1201,39 @@ fhandler_fifo::release_select_sem (const char *from)
|
||||||
ReleaseSemaphore (select_sem, n_release, NULL);
|
ReleaseSemaphore (select_sem, n_release, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Read from a non-blocking pipe and wait for completion. */
|
||||||
|
static NTSTATUS
|
||||||
|
nt_read (HANDLE h, HANDLE evt, PIO_STATUS_BLOCK pio, void *in_ptr, size_t& len)
|
||||||
|
{
|
||||||
|
NTSTATUS status;
|
||||||
|
|
||||||
|
ResetEvent (evt);
|
||||||
|
status = NtReadFile (h, evt, NULL, NULL, pio, in_ptr, len, NULL, NULL);
|
||||||
|
if (status == STATUS_PENDING)
|
||||||
|
{
|
||||||
|
/* Very short-lived */
|
||||||
|
status = NtWaitForSingleObject (evt, FALSE, NULL);
|
||||||
|
if (NT_SUCCESS (status))
|
||||||
|
status = pio->Status;
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
void __reg3
|
void __reg3
|
||||||
fhandler_fifo::raw_read (void *in_ptr, size_t& len)
|
fhandler_fifo::raw_read (void *in_ptr, size_t& len)
|
||||||
{
|
{
|
||||||
|
HANDLE evt;
|
||||||
|
|
||||||
if (!len)
|
if (!len)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (!(evt = CreateEvent (NULL, false, false, NULL)))
|
||||||
|
{
|
||||||
|
__seterrno ();
|
||||||
|
len = (size_t) -1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
int nconnected = 0;
|
int nconnected = 0;
|
||||||
|
@ -1244,17 +1271,15 @@ fhandler_fifo::raw_read (void *in_ptr, size_t& len)
|
||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
IO_STATUS_BLOCK io;
|
IO_STATUS_BLOCK io;
|
||||||
|
|
||||||
status = NtReadFile (fc_handler[j].h, NULL, NULL, NULL,
|
status = nt_read (fc_handler[j].h, evt, &io, in_ptr, len);
|
||||||
&io, in_ptr, len, NULL, NULL);
|
|
||||||
switch (status)
|
switch (status)
|
||||||
{
|
{
|
||||||
case STATUS_SUCCESS:
|
case STATUS_SUCCESS:
|
||||||
case STATUS_BUFFER_OVERFLOW:
|
case STATUS_BUFFER_OVERFLOW:
|
||||||
/* io.Information is supposedly valid in latter case. */
|
|
||||||
if (io.Information > 0)
|
if (io.Information > 0)
|
||||||
{
|
{
|
||||||
len = io.Information;
|
len = io.Information;
|
||||||
goto out;
|
goto unlock_out;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case STATUS_PIPE_EMPTY:
|
case STATUS_PIPE_EMPTY:
|
||||||
|
@ -1265,7 +1290,7 @@ fhandler_fifo::raw_read (void *in_ptr, size_t& len)
|
||||||
fc_handler[j].set_state (fc_disconnected);
|
fc_handler[j].set_state (fc_disconnected);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
debug_printf ("NtReadFile status %y", status);
|
debug_printf ("nt_read status %y", status);
|
||||||
fc_handler[j].set_state (fc_error);
|
fc_handler[j].set_state (fc_error);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1278,8 +1303,7 @@ fhandler_fifo::raw_read (void *in_ptr, size_t& len)
|
||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
IO_STATUS_BLOCK io;
|
IO_STATUS_BLOCK io;
|
||||||
|
|
||||||
status = NtReadFile (fc_handler[i].h, NULL, NULL, NULL,
|
status = nt_read (fc_handler[i].h, evt, &io, in_ptr, len);
|
||||||
&io, in_ptr, len, NULL, NULL);
|
|
||||||
switch (status)
|
switch (status)
|
||||||
{
|
{
|
||||||
case STATUS_SUCCESS:
|
case STATUS_SUCCESS:
|
||||||
|
@ -1290,7 +1314,7 @@ fhandler_fifo::raw_read (void *in_ptr, size_t& len)
|
||||||
if (j < nhandlers)
|
if (j < nhandlers)
|
||||||
fc_handler[j].last_read = false;
|
fc_handler[j].last_read = false;
|
||||||
fc_handler[i].last_read = true;
|
fc_handler[i].last_read = true;
|
||||||
goto out;
|
goto unlock_out;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case STATUS_PIPE_EMPTY:
|
case STATUS_PIPE_EMPTY:
|
||||||
|
@ -1301,7 +1325,7 @@ fhandler_fifo::raw_read (void *in_ptr, size_t& len)
|
||||||
fc_handler[i].set_state (fc_disconnected);
|
fc_handler[i].set_state (fc_disconnected);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
debug_printf ("NtReadFile status %y", status);
|
debug_printf ("nt_read status %y", status);
|
||||||
fc_handler[i].set_state (fc_error);
|
fc_handler[i].set_state (fc_error);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1315,8 +1339,7 @@ fhandler_fifo::raw_read (void *in_ptr, size_t& len)
|
||||||
IO_STATUS_BLOCK io;
|
IO_STATUS_BLOCK io;
|
||||||
|
|
||||||
nconnected++;
|
nconnected++;
|
||||||
status = NtReadFile (fc_handler[i].h, NULL, NULL, NULL,
|
status = nt_read (fc_handler[i].h, evt, &io, in_ptr, len);
|
||||||
&io, in_ptr, len, NULL, NULL);
|
|
||||||
switch (status)
|
switch (status)
|
||||||
{
|
{
|
||||||
case STATUS_SUCCESS:
|
case STATUS_SUCCESS:
|
||||||
|
@ -1327,7 +1350,7 @@ fhandler_fifo::raw_read (void *in_ptr, size_t& len)
|
||||||
if (j < nhandlers)
|
if (j < nhandlers)
|
||||||
fc_handler[j].last_read = false;
|
fc_handler[j].last_read = false;
|
||||||
fc_handler[i].last_read = true;
|
fc_handler[i].last_read = true;
|
||||||
goto out;
|
goto unlock_out;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case STATUS_PIPE_EMPTY:
|
case STATUS_PIPE_EMPTY:
|
||||||
|
@ -1337,25 +1360,25 @@ fhandler_fifo::raw_read (void *in_ptr, size_t& len)
|
||||||
nconnected--;
|
nconnected--;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
debug_printf ("NtReadFile status %y", status);
|
debug_printf ("nt_read status %y", status);
|
||||||
fc_handler[i].set_state (fc_error);
|
fc_handler[i].set_state (fc_error);
|
||||||
nconnected--;
|
nconnected--;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fifo_client_unlock ();
|
|
||||||
if (!nconnected && hit_eof ())
|
if (!nconnected && hit_eof ())
|
||||||
{
|
{
|
||||||
reading_unlock ();
|
|
||||||
len = 0;
|
len = 0;
|
||||||
return;
|
goto unlock_out;
|
||||||
}
|
}
|
||||||
|
fifo_client_unlock ();
|
||||||
maybe_retry:
|
maybe_retry:
|
||||||
reading_unlock ();
|
reading_unlock ();
|
||||||
if (is_nonblocking ())
|
if (is_nonblocking ())
|
||||||
{
|
{
|
||||||
set_errno (EAGAIN);
|
set_errno (EAGAIN);
|
||||||
goto errout;
|
len = (size_t) -1;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1370,7 +1393,8 @@ maybe_retry:
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
set_errno (EINTR);
|
set_errno (EINTR);
|
||||||
goto errout;
|
len = (size_t) -1;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1378,17 +1402,17 @@ maybe_retry:
|
||||||
if (isclosed ())
|
if (isclosed ())
|
||||||
{
|
{
|
||||||
set_errno (EBADF);
|
set_errno (EBADF);
|
||||||
goto errout;
|
len = (size_t) -1;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
errout:
|
unlock_out:
|
||||||
len = (size_t) -1;
|
|
||||||
return;
|
|
||||||
out:
|
|
||||||
fifo_client_unlock ();
|
fifo_client_unlock ();
|
||||||
reading_unlock ();
|
reading_unlock ();
|
||||||
|
out:
|
||||||
if (select_sem)
|
if (select_sem)
|
||||||
release_select_sem ("raw_read");
|
release_select_sem ("raw_read");
|
||||||
|
CloseHandle (evt);
|
||||||
}
|
}
|
||||||
|
|
||||||
int __reg2
|
int __reg2
|
||||||
|
|
Loading…
Reference in New Issue