* fhandler.cc (fhandler_base::wait_overlapped): Reorganize to eliminate gotos

and to hopefully eliminate one race when a signal is detected or there is a
WFMO error.
This commit is contained in:
Christopher Faylor 2008-12-20 19:20:00 +00:00
parent 9ac421686a
commit 0cf888799b
2 changed files with 43 additions and 37 deletions

View File

@ -1,3 +1,9 @@
2008-12-20 Christopher Faylor <me+cygwin@cgf.cx>
* fhandler.cc (fhandler_base::wait_overlapped): Reorganize to eliminate
gotos and to hopefully eliminate one race when a signal is detected or
there is a WFMO error.
2008-12-20 Christopher Faylor <me+cygwin@cgf.cx> 2008-12-20 Christopher Faylor <me+cygwin@cgf.cx>
* pinfo.h (pinfo::thisproc): Declare. Rename from set_myself. * pinfo.h (pinfo::thisproc): Declare. Rename from set_myself.

View File

@ -1682,19 +1682,11 @@ fhandler_base::destroy_overlapped ()
int int
fhandler_base::wait_overlapped (bool inres, bool writing, DWORD *bytes) fhandler_base::wait_overlapped (bool inres, bool writing, DWORD *bytes)
{ {
int res; int res = 0;
*bytes = (DWORD) -1; *bytes = (DWORD) -1;
DWORD err = GetLastError (); DWORD err;
if (!inres && err != ERROR_IO_PENDING) if (inres || ((err = GetLastError ()) == ERROR_IO_PENDING))
{ {
if (err != ERROR_HANDLE_EOF && err != ERROR_BROKEN_PIPE)
goto err;
res = 1;
*bytes = 0;
err = 0;
}
else
{
#ifdef DEBUGGING #ifdef DEBUGGING
if (!get_overlapped ()) if (!get_overlapped ())
system_printf ("get_overlapped is zero?"); system_printf ("get_overlapped is zero?");
@ -1707,39 +1699,47 @@ fhandler_base::wait_overlapped (bool inres, bool writing, DWORD *bytes)
if (&_my_tls == _main_tls) if (&_my_tls == _main_tls)
w4[n++] = signal_arrived; w4[n++] = signal_arrived;
HANDLE h = writing ? get_output_handle () : get_handle (); HANDLE h = writing ? get_output_handle () : get_handle ();
DWORD wres = WaitForMultipleObjects (n, w4, false, INFINITE); DWORD wfres = WaitForMultipleObjects (n, w4, false, INFINITE);
err = 0; if (wfres != WAIT_OBJECT_0)
switch (wres) CancelIo (h);
BOOL wores = GetOverlappedResult (h, get_overlapped (), bytes, false);
bool signalled = !wores && (wfres == WAIT_OBJECT_0 + 1);
if (signalled)
{ {
case WAIT_OBJECT_0:
debug_printf ("normal read");
if (GetOverlappedResult (h, get_overlapped (), bytes, false))
res = 1;
else
{
err = GetLastError ();
goto err;
}
break;
case WAIT_OBJECT_0 + 1:
debug_printf ("got a signal"); debug_printf ("got a signal");
CancelIo (h);
set_errno (EINTR); set_errno (EINTR);
res = 0; res = 0;
break; err = 0;
default: }
else if (!wores)
{
err = GetLastError (); err = GetLastError ();
debug_printf ("WFMO error, %E"); debug_printf ("general error");
goto err; }
break; else
{
debug_printf ("normal read");
res = 1;
err = 0;
} }
} }
goto out;
err: if (!err)
__seterrno_from_win_error (err); /* nothing to do */;
res = -1; else if (err != ERROR_HANDLE_EOF && err != ERROR_BROKEN_PIPE)
out: {
debug_printf ("err %u", err);
__seterrno_from_win_error (err);
res = -1;
}
else
{
res = 1;
*bytes = 0;
err = 0;
debug_printf ("EOF");
}
/* Make sure the event is unsignalled (this is a potential race in a multi-threaded /* Make sure the event is unsignalled (this is a potential race in a multi-threaded
app. Sigh.). Must do this after WFMO and GetOverlappedResult or suffer app. Sigh.). Must do this after WFMO and GetOverlappedResult or suffer
occasional sporadic problems: occasional sporadic problems: