* fhandler.cc (fhandler_base_overlapped::wait_overlapped): Handle
overlapped_fallback error condition like other error conditions. Set res carefully and specifically for each condition rather than resorting to a default. (fhandler_base_overlapped::write_overlapped): Preserve errno in overlapped_fallback condition. Correct write_overlapped_fallback to avoid inappropriate looping. (fhandler_base_overlapped::write_overlapped_fallback): Add some more comments.
This commit is contained in:
parent
ed6b66c88d
commit
904e3e2004
@ -1,3 +1,15 @@
|
||||
2011-03-09 Christopher Faylor <me.cygwin2011@cgf.cx>
|
||||
|
||||
* fhandler.cc (fhandler_base_overlapped::wait_overlapped): Handle
|
||||
overlapped_fallback error condition like other error conditions. Set
|
||||
res carefully and specifically for each condition rather than resorting
|
||||
to a default.
|
||||
(fhandler_base_overlapped::write_overlapped): Preserve errno in
|
||||
overlapped_fallback condition. Correct write_overlapped_fallback to
|
||||
avoid inappropriate looping.
|
||||
(fhandler_base_overlapped::write_overlapped_fallback): Add some more
|
||||
comments.
|
||||
|
||||
2011-03-09 Christopher Faylor <me.cygwin@cgf.cx>
|
||||
|
||||
* fhandler.cc (fhandler_base_overlapped::write_overlapp): Oops!
|
||||
|
@ -1731,14 +1731,15 @@ fhandler_base_overlapped::wait_overlapped (bool inres, bool writing, DWORD *byte
|
||||
if (!get_overlapped ())
|
||||
return inres ? overlapped_success : overlapped_error;
|
||||
|
||||
wait_return res;
|
||||
DWORD err = GetLastError ();
|
||||
if (err == ERROR_NO_SYSTEM_RESOURCES)
|
||||
return overlapped_fallback;
|
||||
|
||||
wait_return res = overlapped_error;
|
||||
if (nonblocking)
|
||||
res = overlapped_fallback;
|
||||
else if (nonblocking)
|
||||
{
|
||||
if (inres || err == ERROR_IO_PENDING)
|
||||
if (!inres && err != ERROR_IO_PENDING)
|
||||
res = overlapped_error;
|
||||
else
|
||||
{
|
||||
io_pending = err == ERROR_IO_PENDING;
|
||||
if (writing && !inres)
|
||||
@ -1747,7 +1748,9 @@ fhandler_base_overlapped::wait_overlapped (bool inres, bool writing, DWORD *byte
|
||||
err = 0;
|
||||
}
|
||||
}
|
||||
else if (inres || err == ERROR_IO_PENDING)
|
||||
else if (!inres && err != ERROR_IO_PENDING)
|
||||
res = overlapped_error;
|
||||
else
|
||||
{
|
||||
#ifdef DEBUGGING
|
||||
if (!get_overlapped ()->hEvent)
|
||||
@ -1768,10 +1771,13 @@ fhandler_base_overlapped::wait_overlapped (bool inres, bool writing, DWORD *byte
|
||||
if (signalled)
|
||||
{
|
||||
debug_printf ("got a signal");
|
||||
if (!_my_tls.call_signal_handler ())
|
||||
set_errno (EINTR);
|
||||
else
|
||||
if (_my_tls.call_signal_handler ())
|
||||
res = overlapped_signal;
|
||||
else
|
||||
{
|
||||
set_errno (EINTR);
|
||||
res = overlapped_error;
|
||||
}
|
||||
*bytes = (DWORD) -1;
|
||||
err = 0;
|
||||
}
|
||||
@ -1779,30 +1785,30 @@ fhandler_base_overlapped::wait_overlapped (bool inres, bool writing, DWORD *byte
|
||||
{
|
||||
err = GetLastError ();
|
||||
debug_printf ("GetOverLappedResult failed, bytes %u", *bytes);
|
||||
res = overlapped_error;
|
||||
}
|
||||
else
|
||||
{
|
||||
err = 0;
|
||||
debug_printf ("normal %s, %u bytes", writing ? "write" : "read", *bytes);
|
||||
res = overlapped_success;
|
||||
err = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!err)
|
||||
/* nothing to do */;
|
||||
else if (err != ERROR_HANDLE_EOF && err != ERROR_BROKEN_PIPE)
|
||||
{
|
||||
debug_printf ("err %u", err);
|
||||
__seterrno_from_win_error (err);
|
||||
*bytes = (DWORD) -1;
|
||||
res = overlapped_error;
|
||||
}
|
||||
else
|
||||
else if (err == ERROR_HANDLE_EOF || err == ERROR_BROKEN_PIPE)
|
||||
{
|
||||
debug_printf ("EOF");
|
||||
*bytes = 0;
|
||||
res = overlapped_success;
|
||||
}
|
||||
else
|
||||
{
|
||||
debug_printf ("err %u", err);
|
||||
__seterrno_from_win_error (err);
|
||||
*bytes = (DWORD) -1;
|
||||
}
|
||||
|
||||
if (writing && (err == ERROR_NO_DATA || err == ERROR_BROKEN_PIPE))
|
||||
raise (SIGPIPE);
|
||||
@ -1848,6 +1854,7 @@ fhandler_base_overlapped::write_overlapped (const void *ptr, size_t len)
|
||||
nbytes = (DWORD) -1;
|
||||
else
|
||||
{
|
||||
int last_errno = get_errno ();
|
||||
bool keep_looping;
|
||||
if (is_nonblocking () && max_atomic_write && len > max_atomic_write)
|
||||
len = max_atomic_write;
|
||||
@ -1857,12 +1864,13 @@ fhandler_base_overlapped::write_overlapped (const void *ptr, size_t len)
|
||||
get_overlapped ());
|
||||
switch (wait_overlapped (res, true, &nbytes, is_nonblocking (), (size_t) len))
|
||||
{
|
||||
case overlapped_fallback:
|
||||
nbytes = write_overlapped_fallback (ptr, len);
|
||||
/* fall through intentionally */;
|
||||
case overlapped_signal:
|
||||
keep_looping = true;
|
||||
break;
|
||||
case overlapped_fallback:
|
||||
set_errno (last_errno); /* Avoid setting a random EFBIG errno */
|
||||
nbytes = write_overlapped_fallback (ptr, len);
|
||||
/* fall through intentionally */;
|
||||
default: /* Added to quiet gcc */
|
||||
case overlapped_success:
|
||||
case overlapped_error:
|
||||
@ -1885,6 +1893,7 @@ ssize_t __stdcall __attribute__ ((regparm (3)))
|
||||
fhandler_base_overlapped::write_overlapped_fallback (const void *ptr, size_t orig_len)
|
||||
{
|
||||
size_t chunk;
|
||||
/* So far, in testing, only the first if test has been necessary */
|
||||
if (orig_len > MAX_OVERLAPPED_WRITE_LEN)
|
||||
chunk = MAX_OVERLAPPED_WRITE_LEN;
|
||||
else if (orig_len > MIN_OVERLAPPED_WRITE_LEN)
|
||||
@ -1893,6 +1902,10 @@ fhandler_base_overlapped::write_overlapped_fallback (const void *ptr, size_t ori
|
||||
chunk = orig_len / 4;
|
||||
ssize_t nbytes = 0;
|
||||
DWORD nbytes_now = 0;
|
||||
/* Write to fd in smaller chunks, accumlating a total.
|
||||
If there's an error, just return the accumulated total
|
||||
unless the first write fails, in which case return value
|
||||
from wait_overlapped(). */
|
||||
while ((size_t) nbytes < orig_len)
|
||||
{
|
||||
size_t left = orig_len - nbytes;
|
||||
@ -1913,11 +1926,11 @@ fhandler_base_overlapped::write_overlapped_fallback (const void *ptr, size_t ori
|
||||
nbytes += nbytes_now;
|
||||
/* fall through intentionally */
|
||||
case overlapped_signal:
|
||||
break; /* keep looping */
|
||||
break; /* keep looping */
|
||||
case overlapped_error:
|
||||
case overlapped_fallback: /* Could make this more adaptive
|
||||
case overlapped_fallback: /* XXX Could make this more adaptive
|
||||
if needed */
|
||||
orig_len = 0; /* terminate loop */
|
||||
orig_len = 0; /* terminate loop */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user