summaryrefslogtreecommitdiffstats
path: root/winsup/cygwin/fhandler.cc
diff options
context:
space:
mode:
authorChristopher Faylor <me@cgf.cx>2011-12-18 04:07:47 +0000
committerChristopher Faylor <me@cgf.cx>2011-12-18 04:07:47 +0000
commitd004a279716433bf3dc8477bc838d490028d223d (patch)
tree31e07ddaf6d7fc259343f355df0395f0baba43a9 /winsup/cygwin/fhandler.cc
parent1b23b30b29eebbe7c9953f2a7470f31a0feb8702 (diff)
downloadcygnal-d004a279716433bf3dc8477bc838d490028d223d.tar.gz
cygnal-d004a279716433bf3dc8477bc838d490028d223d.tar.bz2
cygnal-d004a279716433bf3dc8477bc838d490028d223d.zip
* 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.
Diffstat (limited to 'winsup/cygwin/fhandler.cc')
-rw-r--r--winsup/cygwin/fhandler.cc57
1 files changed, 35 insertions, 22 deletions
diff --git a/winsup/cygwin/fhandler.cc b/winsup/cygwin/fhandler.cc
index 6624bc7da..a93b45436 100644
--- a/winsup/cygwin/fhandler.cc
+++ b/winsup/cygwin/fhandler.cc
@@ -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;
+ }
}
}