* 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:
parent
1b23b30b29
commit
d004a27971
|
@ -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>
|
2011-12-17 Corinna Vinschen <vinschen@redhat.com>
|
||||||
|
|
||||||
* dcrt0.cc (_dll_crt0): Fix formatting.
|
* dcrt0.cc (_dll_crt0): Fix formatting.
|
||||||
|
|
|
@ -1148,7 +1148,6 @@ fhandler_base::close ()
|
||||||
paranoid_printf ("CloseHandle failed, %E");
|
paranoid_printf ("CloseHandle failed, %E");
|
||||||
__seterrno ();
|
__seterrno ();
|
||||||
}
|
}
|
||||||
isclosed (true);
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1219,9 +1218,8 @@ fhandler_base_overlapped::close ()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Cancelling seems to be necessary for cases where a reader is
|
/* Cancelling seems to be necessary for cases where a reader is
|
||||||
still executing either in another thread or when a signal handler
|
still executing when a signal handler performs a close. */
|
||||||
performs a close. */
|
|
||||||
CancelIo (get_io_handle ());
|
CancelIo (get_io_handle ());
|
||||||
destroy_overlapped ();
|
destroy_overlapped ();
|
||||||
res = fhandler_base::close ();
|
res = fhandler_base::close ();
|
||||||
|
@ -1882,6 +1880,7 @@ fhandler_base_overlapped::destroy_overlapped ()
|
||||||
OVERLAPPED *ov = get_overlapped ();
|
OVERLAPPED *ov = get_overlapped ();
|
||||||
if (ov && ov->hEvent)
|
if (ov && ov->hEvent)
|
||||||
{
|
{
|
||||||
|
SetEvent (ov->hEvent);
|
||||||
CloseHandle (ov->hEvent);
|
CloseHandle (ov->hEvent);
|
||||||
ov->hEvent = NULL;
|
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 ();
|
HANDLE h = writing ? get_output_handle () : get_handle ();
|
||||||
BOOL wores;
|
BOOL wores;
|
||||||
if (isclosed ())
|
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
|
else
|
||||||
{
|
{
|
||||||
/* Cancelling here to prevent races. It's possible that the I/O has
|
/* 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 ();
|
err = GetLastError ();
|
||||||
ResetEvent (get_overlapped ()->hEvent); /* Probably not needed but CYA */
|
ResetEvent (get_overlapped ()->hEvent); /* Probably not needed but CYA */
|
||||||
debug_printf ("wfres %d, wores %d, bytes %u", wfres, wores, *bytes);
|
debug_printf ("wfres %d, wores %d, bytes %u", wfres, wores, *bytes);
|
||||||
}
|
if (wores)
|
||||||
if (wores)
|
res = overlapped_success; /* operation succeeded */
|
||||||
res = overlapped_success; /* operation succeeded */
|
else if (wfres == WAIT_OBJECT_0 + 1)
|
||||||
else if (wfres == WAIT_OBJECT_0 + 1)
|
{
|
||||||
{
|
err = ERROR_INVALID_AT_INTERRUPT_TIME; /* forces an EINTR below */
|
||||||
err = ERROR_INVALID_AT_INTERRUPT_TIME; /* forces an EINTR below */
|
debug_printf ("signal");
|
||||||
debug_printf ("signal");
|
res = overlapped_error;
|
||||||
res = overlapped_error;
|
}
|
||||||
}
|
else if (wfres == WAIT_OBJECT_0 + 2)
|
||||||
else if (nonblocking)
|
pthread::static_cancel_self (); /* never returns */
|
||||||
res = overlapped_nonblocking_no_data; /* more handling below */
|
else if (nonblocking)
|
||||||
else if (wfres == WAIT_OBJECT_0 + 2)
|
res = overlapped_nonblocking_no_data; /* more handling below */
|
||||||
pthread::static_cancel_self (); /* never returns */
|
else
|
||||||
else
|
{
|
||||||
{
|
debug_printf ("GetOverLappedResult failed, h %p, bytes %u, %E", h, *bytes);
|
||||||
debug_printf ("GetOverLappedResult failed, h %p, bytes %u, %E", h, *bytes);
|
res = overlapped_error;
|
||||||
res = overlapped_error;
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1373,6 +1373,7 @@ close (int fd)
|
||||||
res = -1;
|
res = -1;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
cfd->isclosed (true);
|
||||||
res = cfd->close_with_arch ();
|
res = cfd->close_with_arch ();
|
||||||
cfd.release ();
|
cfd.release ();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue