* fhandler.cc (fhandler_base::close): Move setting isclosed() from here to

closed().
(fhandler_base_overlapped::close): Correct comment.
(fhandler_base_overlapped::destroy_overlapped): Signal overlapped event before
closing it to potentially wake up a waiting thread.
(fhandler_base_overlapped::wait_overlapped): Expand setting of err when closed
to encompass non-signal event.  Test for a cancel event before making
nonblocking decisions.
* syscalls.cc (close): Set closed flag here so that any concurrently executing
functions will be notified ASAP.
This commit is contained in:
Christopher Faylor 2011-12-18 04:07:47 +00:00
parent 1b23b30b29
commit d004a27971
3 changed files with 49 additions and 22 deletions

View File

@ -1,3 +1,16 @@
2011-12-17 Christopher Faylor <me.cygwin2011@cgf.cx>
* fhandler.cc (fhandler_base::close): Move setting isclosed() from here
to closed().
(fhandler_base_overlapped::close): Correct comment.
(fhandler_base_overlapped::destroy_overlapped): Signal overlapped event
before closing it to potentially wake up a waiting thread.
(fhandler_base_overlapped::wait_overlapped): Expand setting of err when
closed to encompass non-signal event. Test for a cancel event before
making nonblocking decisions.
* syscalls.cc (close): Set closed flag here so that any concurrently
executing functions will be notified ASAP.
2011-12-17 Corinna Vinschen <vinschen@redhat.com>
* dcrt0.cc (_dll_crt0): Fix formatting.

View File

@ -1148,7 +1148,6 @@ fhandler_base::close ()
paranoid_printf ("CloseHandle failed, %E");
__seterrno ();
}
isclosed (true);
return res;
}
@ -1219,9 +1218,8 @@ fhandler_base_overlapped::close ()
}
else
{
/* Cancelling seems to be necessary for cases where a reader is
still executing either in another thread or when a signal handler
performs a close. */
/* Cancelling seems to be necessary for cases where a reader is
still executing when a signal handler performs a close. */
CancelIo (get_io_handle ());
destroy_overlapped ();
res = fhandler_base::close ();
@ -1882,6 +1880,7 @@ fhandler_base_overlapped::destroy_overlapped ()
OVERLAPPED *ov = get_overlapped ();
if (ov && ov->hEvent)
{
SetEvent (ov->hEvent);
CloseHandle (ov->hEvent);
ov->hEvent = NULL;
}
@ -1931,7 +1930,21 @@ fhandler_base_overlapped::wait_overlapped (bool inres, bool writing, DWORD *byte
HANDLE h = writing ? get_output_handle () : get_handle ();
BOOL wores;
if (isclosed ())
wores = 0; /* closed in another thread or via signal handler */
{
switch (err)
{
case WAIT_OBJECT_0:
err = ERROR_INVALID_HANDLE;
break;
case WAIT_OBJECT_0 + 1:
err = ERROR_INVALID_AT_INTERRUPT_TIME;
break;
default:
err = GetLastError ();
break;
}
res = overlapped_error;
}
else
{
/* Cancelling here to prevent races. It's possible that the I/O has
@ -1945,23 +1958,23 @@ fhandler_base_overlapped::wait_overlapped (bool inres, bool writing, DWORD *byte
err = GetLastError ();
ResetEvent (get_overlapped ()->hEvent); /* Probably not needed but CYA */
debug_printf ("wfres %d, wores %d, bytes %u", wfres, wores, *bytes);
}
if (wores)
res = overlapped_success; /* operation succeeded */
else if (wfres == WAIT_OBJECT_0 + 1)
{
err = ERROR_INVALID_AT_INTERRUPT_TIME; /* forces an EINTR below */
debug_printf ("signal");
res = overlapped_error;
}
else if (nonblocking)
res = overlapped_nonblocking_no_data; /* more handling below */
else if (wfres == WAIT_OBJECT_0 + 2)
pthread::static_cancel_self (); /* never returns */
else
{
debug_printf ("GetOverLappedResult failed, h %p, bytes %u, %E", h, *bytes);
res = overlapped_error;
if (wores)
res = overlapped_success; /* operation succeeded */
else if (wfres == WAIT_OBJECT_0 + 1)
{
err = ERROR_INVALID_AT_INTERRUPT_TIME; /* forces an EINTR below */
debug_printf ("signal");
res = overlapped_error;
}
else if (wfres == WAIT_OBJECT_0 + 2)
pthread::static_cancel_self (); /* never returns */
else if (nonblocking)
res = overlapped_nonblocking_no_data; /* more handling below */
else
{
debug_printf ("GetOverLappedResult failed, h %p, bytes %u, %E", h, *bytes);
res = overlapped_error;
}
}
}

View File

@ -1373,6 +1373,7 @@ close (int fd)
res = -1;
else
{
cfd->isclosed (true);
res = cfd->close_with_arch ();
cfd.release ();
}