diff options
Diffstat (limited to 'winsup/cygwin/select.cc')
-rw-r--r-- | winsup/cygwin/select.cc | 145 |
1 files changed, 71 insertions, 74 deletions
diff --git a/winsup/cygwin/select.cc b/winsup/cygwin/select.cc index e1906cb14..41636d179 100644 --- a/winsup/cygwin/select.cc +++ b/winsup/cygwin/select.cc @@ -1,7 +1,7 @@ /* select.cc Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, - 2005, 2006, 2007, 2008, 2009 Red Hat, Inc. + 2005, 2006, 2007, 2008, 2009, 2010 Red Hat, Inc. This file is part of Cygwin. @@ -429,12 +429,17 @@ no_verify (select_record *, fd_set *, fd_set *, fd_set *) static int peek_pipe (select_record *s, bool from_select) { + HANDLE h; + set_handle_or_return_if_not_open (h, s); + int n = 0; int gotone = 0; - fhandler_base *fh = s->fh; + fhandler_base *fh = (fhandler_base *) s->fh; - HANDLE h; - set_handle_or_return_if_not_open (h, s); + /* Don't check if this is a non-blocking fd and I/O is still active. + That could give a false-positive with peek_pipe and friends. */ + if (fh->has_ongoing_io ()) + return 0; /* Don't perform complicated tests if we don't need to. */ if (!s->read_selected && !s->except_selected) @@ -577,72 +582,35 @@ out: static int start_thread_pipe (select_record *me, select_stuff *stuff); -select_pipe_info::select_pipe_info () -{ - n = 1; - w4[0] = CreateEvent (&sec_none_nih, true, false, NULL); -} - -select_pipe_info::~select_pipe_info () -{ - if (thread) - { - SetEvent (w4[0]); - stop_thread = true; - thread->detach (); - } - ForceCloseHandle (w4[0]); -} - -void -select_pipe_info::add_watch_handle (fhandler_pipe *fh) -{ - if (fh->get_overlapped () && fh->get_overlapped ()->hEvent) - w4[n++] = fh->get_overlapped ()->hEvent; -} - static DWORD WINAPI thread_pipe (void *arg) { select_pipe_info *pi = (select_pipe_info *) arg; - bool gotone = false; DWORD sleep_time = 0; + bool looping = true; - for (;;) + while (looping) { - select_record *s = pi->start; - if (pi->n > 1) - switch (WaitForMultipleObjects (pi->n, pi->w4, false, INFINITE)) - { - case WAIT_OBJECT_0: - goto out; - default: - break; - } - while ((s = s->next)) + for (select_record *s = pi->start; (s = s->next); ) if (s->startup == start_thread_pipe) { if (peek_pipe (s, true)) - gotone = true; + looping = false; if (pi->stop_thread) { select_printf ("stopping"); - goto out; + looping = false; + break; } } - /* Paranoid check */ - if (pi->stop_thread) - { - select_printf ("stopping from outer loop"); - break; - } - if (gotone) + if (!looping) break; Sleep (sleep_time >> 3); if (sleep_time < 80) ++sleep_time; + if (pi->stop_thread) + break; } -out: return 0; } @@ -667,9 +635,12 @@ start_thread_pipe (select_record *me, select_stuff *stuff) static void pipe_cleanup (select_record *, select_stuff *stuff) { - if (stuff->device_specific_pipe) + select_pipe_info *pi = (select_pipe_info *) stuff->device_specific_pipe; + if (pi && pi->thread) { - delete stuff->device_specific_pipe; + pi->stop_thread = true; + pi->thread->detach (); + delete pi; stuff->device_specific_pipe = NULL; } } @@ -691,7 +662,6 @@ fhandler_pipe::select_read (select_stuff *ss) if (!ss->device_specific_pipe && (ss->device_specific_pipe = new select_pipe_info) == NULL) return NULL; - ss->device_specific_pipe->add_watch_handle (this); select_record *s = ss->start.next; s->startup = start_thread_pipe; @@ -709,7 +679,6 @@ fhandler_pipe::select_write (select_stuff *ss) if (!ss->device_specific_pipe && (ss->device_specific_pipe = new select_pipe_info) == NULL) return NULL; - ss->device_specific_pipe->add_watch_handle (this); select_record *s = ss->start.next; s->startup = start_thread_pipe; s->peek = peek_pipe; @@ -726,7 +695,6 @@ fhandler_pipe::select_except (select_stuff *ss) if (!ss->device_specific_pipe && (ss->device_specific_pipe = new select_pipe_info) == NULL) return NULL; - ss->device_specific_pipe->add_watch_handle (this); select_record *s = ss->start.next; s->startup = start_thread_pipe; s->peek = peek_pipe; @@ -906,19 +874,50 @@ fhandler_console::select_except (select_stuff *ss) select_record * fhandler_tty_common::select_read (select_stuff *ss) { - return ((fhandler_pipe *) this)->fhandler_pipe::select_read (ss); + if (!ss->device_specific_pipe + && (ss->device_specific_pipe = new select_pipe_info) == NULL) + return NULL; + + select_record *s = ss->start.next; + s->startup = start_thread_pipe; + s->peek = peek_pipe; + s->verify = verify_ok; + s->cleanup = pipe_cleanup; + s->read_selected = true; + s->read_ready = false; + return s; } select_record * fhandler_tty_common::select_write (select_stuff *ss) { - return ((fhandler_pipe *) this)->fhandler_pipe::select_write (ss); + if (!ss->device_specific_pipe + && (ss->device_specific_pipe = new select_pipe_info) == NULL) + return NULL; + select_record *s = ss->start.next; + s->startup = start_thread_pipe; + s->peek = peek_pipe; + s->verify = verify_ok; + s->cleanup = pipe_cleanup; + s->write_selected = true; + s->write_ready = false; + return s; } select_record * fhandler_tty_common::select_except (select_stuff *ss) { - return ((fhandler_pipe *) this)->fhandler_pipe::select_except (ss); + if (!ss->device_specific_pipe + && (ss->device_specific_pipe = new select_pipe_info) == NULL) + return NULL; + select_record *s = ss->start.next; + s->startup = start_thread_pipe; + s->peek = peek_pipe; + s->verify = verify_ok; + s->cleanup = pipe_cleanup; + s->except_selected = true; + s->except_ready = false; + return s; } static int @@ -1098,25 +1097,23 @@ static DWORD WINAPI thread_serial (void *arg) { select_serial_info *si = (select_serial_info *) arg; - bool gotone = false; + bool looping = true; - for (;;) - { - select_record *s = si->start; - while ((s = s->next)) - if (s->startup == start_thread_serial) - { - if (peek_serial (s, true)) - gotone = true; - } - if (si->stop_thread) + while (looping) + for (select_record *s = si->start; (s = s->next); ) + if (s->startup != start_thread_serial) + continue; + else { - select_printf ("stopping"); - break; + if (peek_serial (s, true)) + looping = false; + if (si->stop_thread) + { + select_printf ("stopping"); + looping = false; + break; + } } - if (gotone) - break; - } select_printf ("exiting"); return 0; |