mirror of
git://sourceware.org/git/newlib-cygwin.git
synced 2025-03-02 13:05:42 +08:00
Cygwin: FIFO: fix signal handling in raw_read and raw_write
cygwait wasn't being called correctly. Also do some minor cleanup in raw_read and raw_write.
This commit is contained in:
parent
8c187cceaa
commit
b23dcaa411
@ -640,11 +640,15 @@ ssize_t __reg3
|
|||||||
fhandler_fifo::raw_write (const void *ptr, size_t len)
|
fhandler_fifo::raw_write (const void *ptr, size_t len)
|
||||||
{
|
{
|
||||||
ssize_t ret = -1;
|
ssize_t ret = -1;
|
||||||
size_t nbytes = 0, chunk;
|
size_t nbytes = 0;
|
||||||
|
ULONG chunk;
|
||||||
NTSTATUS status = STATUS_SUCCESS;
|
NTSTATUS status = STATUS_SUCCESS;
|
||||||
IO_STATUS_BLOCK io;
|
IO_STATUS_BLOCK io;
|
||||||
HANDLE evt = NULL;
|
HANDLE evt = NULL;
|
||||||
|
|
||||||
|
if (!len)
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (len <= max_atomic_write)
|
if (len <= max_atomic_write)
|
||||||
chunk = len;
|
chunk = len;
|
||||||
else if (is_nonblocking ())
|
else if (is_nonblocking ())
|
||||||
@ -654,7 +658,10 @@ fhandler_fifo::raw_write (const void *ptr, size_t len)
|
|||||||
|
|
||||||
/* Create a wait event if the FIFO is in blocking mode. */
|
/* Create a wait event if the FIFO is in blocking mode. */
|
||||||
if (!is_nonblocking () && !(evt = CreateEvent (NULL, false, false, NULL)))
|
if (!is_nonblocking () && !(evt = CreateEvent (NULL, false, false, NULL)))
|
||||||
return -1;
|
{
|
||||||
|
__seterrno ();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Write in chunks, accumulating a total. If there's an error, just
|
/* Write in chunks, accumulating a total. If there's an error, just
|
||||||
return the accumulated total unless the first write fails, in
|
return the accumulated total unless the first write fails, in
|
||||||
@ -663,33 +670,35 @@ fhandler_fifo::raw_write (const void *ptr, size_t len)
|
|||||||
{
|
{
|
||||||
ULONG_PTR nbytes_now = 0;
|
ULONG_PTR nbytes_now = 0;
|
||||||
size_t left = len - nbytes;
|
size_t left = len - nbytes;
|
||||||
size_t len1;
|
ULONG len1;
|
||||||
|
DWORD waitret = WAIT_OBJECT_0;
|
||||||
|
|
||||||
if (left > chunk)
|
if (left > chunk)
|
||||||
len1 = chunk;
|
len1 = chunk;
|
||||||
else
|
else
|
||||||
len1 = left;
|
len1 = (ULONG) left;
|
||||||
nbytes_now = 0;
|
nbytes_now = 0;
|
||||||
status = NtWriteFile (get_handle (), evt, NULL, NULL, &io,
|
status = NtWriteFile (get_handle (), evt, NULL, NULL, &io,
|
||||||
(PVOID) ptr, len1, NULL, NULL);
|
(PVOID) ptr, len1, NULL, NULL);
|
||||||
if (evt && status == STATUS_PENDING)
|
if (evt && status == STATUS_PENDING)
|
||||||
{
|
{
|
||||||
DWORD waitret = cygwait (evt, cw_infinite, cw_cancel | cw_sig_eintr);
|
waitret = cygwait (evt);
|
||||||
switch (waitret)
|
if (waitret == WAIT_OBJECT_0)
|
||||||
{
|
status = io.Status;
|
||||||
case WAIT_OBJECT_0:
|
|
||||||
status = io.Status;
|
|
||||||
break;
|
|
||||||
case WAIT_SIGNALED:
|
|
||||||
status = STATUS_THREAD_SIGNALED;
|
|
||||||
break;
|
|
||||||
case WAIT_CANCELED:
|
|
||||||
status = STATUS_THREAD_CANCELED;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (NT_SUCCESS (status))
|
if (waitret == WAIT_CANCELED)
|
||||||
|
status = STATUS_THREAD_CANCELED;
|
||||||
|
else if (waitret == WAIT_SIGNALED)
|
||||||
|
status = STATUS_THREAD_SIGNALED;
|
||||||
|
else if (isclosed ()) /* A signal handler might have closed the fd. */
|
||||||
|
{
|
||||||
|
if (waitret == WAIT_OBJECT_0)
|
||||||
|
set_errno (EBADF);
|
||||||
|
else
|
||||||
|
__seterrno ();
|
||||||
|
len = (size_t) -1;
|
||||||
|
}
|
||||||
|
else if (NT_SUCCESS (status))
|
||||||
{
|
{
|
||||||
nbytes_now = io.Information;
|
nbytes_now = io.Information;
|
||||||
/* NtWriteFile returns success with # of bytes written == 0
|
/* NtWriteFile returns success with # of bytes written == 0
|
||||||
@ -714,7 +723,7 @@ fhandler_fifo::raw_write (const void *ptr, size_t len)
|
|||||||
}
|
}
|
||||||
if (evt)
|
if (evt)
|
||||||
CloseHandle (evt);
|
CloseHandle (evt);
|
||||||
if (status == STATUS_THREAD_SIGNALED && !_my_tls.call_signal_handler ())
|
if (status == STATUS_THREAD_SIGNALED && ret < 0)
|
||||||
set_errno (EINTR);
|
set_errno (EINTR);
|
||||||
else if (status == STATUS_THREAD_CANCELED)
|
else if (status == STATUS_THREAD_CANCELED)
|
||||||
pthread::static_cancel_self ();
|
pthread::static_cancel_self ();
|
||||||
@ -784,6 +793,9 @@ fhandler_fifo::raw_read (void *in_ptr, size_t& len)
|
|||||||
if (res < 0 || (res == 0 && !listen_client ()))
|
if (res < 0 || (res == 0 && !listen_client ()))
|
||||||
goto errout;
|
goto errout;
|
||||||
|
|
||||||
|
if (!len)
|
||||||
|
return;
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
if (hit_eof ())
|
if (hit_eof ())
|
||||||
@ -827,21 +839,32 @@ fhandler_fifo::raw_read (void *in_ptr, size_t& len)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Allow interruption. Copied from
|
/* Allow interruption. */
|
||||||
fhandler_socket_unix::open_reparse_point. */
|
DWORD waitret = cygwait (NULL, cw_nowait, cw_cancel | cw_sig_eintr);
|
||||||
pthread_testcancel ();
|
if (waitret == WAIT_CANCELED)
|
||||||
if (cygwait (NULL, cw_nowait, cw_sig_eintr) == WAIT_SIGNALED
|
pthread::static_cancel_self ();
|
||||||
&& !_my_tls.call_signal_handler ())
|
else if (waitret == WAIT_SIGNALED)
|
||||||
{
|
{
|
||||||
set_errno (EINTR);
|
if (_my_tls.call_signal_handler ())
|
||||||
goto errout;
|
continue;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
set_errno (EINTR);
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/* Don't hog the CPU. */
|
|
||||||
Sleep (1);
|
|
||||||
}
|
}
|
||||||
|
/* We might have been closed by a signal handler or another thread. */
|
||||||
|
if (isclosed ())
|
||||||
|
{
|
||||||
|
set_errno (EBADF);
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
/* Don't hog the CPU. */
|
||||||
|
Sleep (1);
|
||||||
}
|
}
|
||||||
errout:
|
errout:
|
||||||
len = -1;
|
len = (size_t) -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int __reg2
|
int __reg2
|
||||||
|
Loading…
x
Reference in New Issue
Block a user