Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'winsup/cygwin/select.cc')
-rw-r--r--winsup/cygwin/select.cc566
1 files changed, 268 insertions, 298 deletions
diff --git a/winsup/cygwin/select.cc b/winsup/cygwin/select.cc
index e66d078c8..c540563fd 100644
--- a/winsup/cygwin/select.cc
+++ b/winsup/cygwin/select.cc
@@ -1,6 +1,6 @@
/* select.cc
- Copyright 1996, 1997, 1998, 1999, 2000, 2001 Red Hat, Inc.
+ Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
Written by Christopher Faylor of Cygnus Solutions
cgf@cygnus.com
@@ -39,10 +39,10 @@ details. */
#include "path.h"
#include "dtable.h"
#include "cygheap.h"
-#include "sync.h"
#include "sigproc.h"
#include "perthread.h"
#include "tty.h"
+#include "cygthread.h"
/*
* All these defines below should be in sys/types.h
@@ -71,7 +71,7 @@ typedef long fd_mask;
#define NULL_fd_set ((fd_set *) NULL)
#define sizeof_fd_set(n) \
- ((unsigned) (NULL_fd_set->fds_bits + unix_howmany((n), UNIX_NFDBITS)))
+ ((unsigned) (NULL_fd_set->fds_bits + unix_howmany ((n), UNIX_NFDBITS)))
#define UNIX_FD_SET(n, p) \
((p)->fds_bits[(n)/UNIX_NFDBITS] |= (1L << ((n) % UNIX_NFDBITS)))
#define UNIX_FD_CLR(n, p) \
@@ -84,30 +84,12 @@ typedef long fd_mask;
#define allocfd_set(n) ((fd_set *) memset (alloca (sizeof_fd_set (n)), 0, sizeof_fd_set (n)))
#define copyfd_set(to, from, n) memcpy (to, from, sizeof_fd_set (n));
-/* Make a fhandler_foo::ready_for_ready method.
- Assumption: The "ready_for_read" methods are called with one level of
- signal blocking. */
-#define MAKEready(what) \
-int \
-fhandler_##what::ready_for_read (int fd, DWORD howlong, int ignra) \
-{ \
- select_record me (this); \
- me.fd = fd; \
- (void) select_read (&me); \
- while (!peek_##what (&me, ignra) && howlong == INFINITE) \
- if (fd >= 0 && cygheap->fdtab.not_open (fd)) \
- break; \
- else if (WaitForSingleObject (signal_arrived, 10) == WAIT_OBJECT_0) \
- break; \
- return me.read_ready; \
-}
-
#define set_handle_or_return_if_not_open(h, s) \
h = (s)->fh->get_handle (); \
if (cygheap->fdtab.not_open ((s)->fd)) \
{ \
- (s)->saw_error = TRUE; \
- set_errno (EBADF); \
+ (s)->saw_error = true; \
+ set_sig_errno (EBADF); \
return -1; \
} \
@@ -228,28 +210,16 @@ select_stuff::test_and_set (int i, fd_set *readfds, fd_set *writefds,
return 1; /* nothing to do */
if (s->read_ready || s->write_ready || s->except_ready)
- always_ready = TRUE;
+ always_ready = true;
if (s->windows_handle || s->windows_handle || s->windows_handle)
- windows_used = TRUE;
+ windows_used = true;
s->next = start.next;
start.next = s;
return 1;
}
-/* Poll every fd in the select chain. Set appropriate fd in mask. */
-int
-select_stuff::poll (fd_set *readfds, fd_set *writefds, fd_set *exceptfds)
-{
- int n = 0;
- select_record *s = &start;
- while ((s = s->next))
- n += s->poll (s, readfds, writefds, exceptfds);
- select_printf ("returning %d", n);
- return n;
-}
-
/* The heart of select. Waits for an fd to do something interesting. */
int
select_stuff::wait (fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
@@ -268,7 +238,7 @@ select_stuff::wait (fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
{
if (m > MAXIMUM_WAIT_OBJECTS)
{
- set_errno (EINVAL);
+ set_sig_errno (EINVAL);
return -1;
}
if (!s->startup (s, this))
@@ -315,12 +285,16 @@ select_stuff::wait (fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
select_printf ("woke up. wait_ret %d. verifying", wait_ret);
s = &start;
int gotone = FALSE;
+ /* Some types of object (e.g., consoles) wake up on "inappropriate" events
+ like mouse movements. The verify function will detect these situations.
+ If it returns false, then this wakeup was a false alarm and we should go
+ back to waiting. */
while ((s = s->next))
if (s->saw_error)
return -1; /* Somebody detected an error */
else if ((((wait_ret >= m && s->windows_handle) || s->h == w4[wait_ret])) &&
s->verify (s, readfds, writefds, exceptfds))
- gotone = TRUE;
+ gotone = true;
select_printf ("gotone %d", gotone);
if (gotone)
@@ -351,7 +325,7 @@ out:
static int
set_bits (select_record *me, fd_set *readfds, fd_set *writefds,
- fd_set *exceptfds)
+ fd_set *exceptfds)
{
int ready = 0;
select_printf ("me %p, testing fd %d (%s)", me, me->fd, me->fh->get_name ());
@@ -363,17 +337,39 @@ set_bits (select_record *me, fd_set *readfds, fd_set *writefds,
if (me->write_selected && me->write_ready)
{
UNIX_FD_SET (me->fd, writefds);
+ if (me->except_on_write && me->fh->get_device () == FH_SOCKET)
+ ((fhandler_socket *) me->fh)->set_connect_state (CONNECTED);
ready++;
}
- if (me->except_ready && me->except_ready)
+ if ((me->except_selected || me->except_on_write) && me->except_ready)
{
- UNIX_FD_SET (me->fd, exceptfds);
+ if (me->except_on_write) /* Only on sockets */
+ {
+ UNIX_FD_SET (me->fd, writefds);
+ if (me->fh->get_device () == FH_SOCKET)
+ ((fhandler_socket *) me->fh)->set_connect_state (CONNECTED);
+ }
+ if (me->except_selected)
+ UNIX_FD_SET (me->fd, exceptfds);
ready++;
}
select_printf ("ready %d", ready);
return ready;
}
+/* Poll every fd in the select chain. Set appropriate fd in mask. */
+int
+select_stuff::poll (fd_set *readfds, fd_set *writefds, fd_set *exceptfds)
+{
+ int n = 0;
+ select_record *s = &start;
+ while ((s = s->next))
+ n += (!s->peek || s->peek (s, true)) ?
+ set_bits (s, readfds, writefds, exceptfds) : 0;
+ select_printf ("returning %d", n);
+ return n;
+}
+
static int
verify_true (select_record *, fd_set *, fd_set *, fd_set *)
{
@@ -400,7 +396,7 @@ no_verify (select_record *, fd_set *, fd_set *, fd_set *)
}
static int
-peek_pipe (select_record *s, int ignra, HANDLE guard_mutex = NULL)
+peek_pipe (select_record *s, bool from_select)
{
int n = 0;
int gotone = 0;
@@ -409,6 +405,15 @@ peek_pipe (select_record *s, int ignra, HANDLE guard_mutex = NULL)
HANDLE h;
set_handle_or_return_if_not_open (h, s);
+ /* pipes require a guard mutex to guard against the situation where multiple
+ readers are attempting to read from the same pipe. In this scenario, it
+ is possible for PeekNamedPipe to report available data to two readers but
+ only one will actually get the data. This will result in the other reader
+ entering fhandler_base::raw_read and blocking indefinitely in an interruptible
+ state. This causes things like "make -j2" to hang. So, for the non-select case
+ we use the pipe mutex, if it is available. */
+ HANDLE guard_mutex = from_select ? NULL : fh->get_guard ();
+
/* Don't perform complicated tests if we don't need to. */
if (!s->read_selected && !s->except_selected)
goto out;
@@ -428,22 +433,22 @@ peek_pipe (select_record *s, int ignra, HANDLE guard_mutex = NULL)
case FH_TTYM:
if (((fhandler_pty_master *)fh)->need_nl)
{
- gotone = s->read_ready = 1;
+ gotone = s->read_ready = true;
goto out;
}
break;
default:
- if (!ignra && fh->get_readahead_valid ())
+ if (fh->get_readahead_valid ())
{
select_printf ("readahead");
- gotone = s->read_ready = 1;
+ gotone = s->read_ready = true;
goto out;
}
}
if (fh->bg_check (SIGTTIN) <= bg_eof)
{
- gotone = s->read_ready = 1;
+ gotone = s->read_ready = true;
goto out;
}
}
@@ -455,34 +460,48 @@ peek_pipe (select_record *s, int ignra, HANDLE guard_mutex = NULL)
select_printf ("%s, PeekNamedPipe failed, %E", fh->get_name ());
n = -1;
}
- else if (n && guard_mutex
- && WaitForSingleObject (guard_mutex, 0) != WAIT_OBJECT_0)
+ else if (!n || !guard_mutex)
+ /* no guard mutex or nothing to read from the pipe. */;
+ else if (WaitForSingleObject (guard_mutex, 0) != WAIT_OBJECT_0)
{
select_printf ("%s, couldn't get mutex %p, %E", fh->get_name (),
- guard_mutex);
+ guard_mutex);
n = 0;
}
+ else
+ {
+ /* Now that we have the mutex, make sure that no one else has snuck
+ in and grabbed the data that we originally saw. */
+ if (!PeekNamedPipe (h, NULL, 0, NULL, (DWORD *) &n, NULL))
+ {
+ select_printf ("%s, PeekNamedPipe failed, %E", fh->get_name ());
+ n = -1;
+ }
+ if (n <= 0)
+ ReleaseMutex (guard_mutex); /* Oops. We lost the race. */
+ }
if (n < 0)
{
+ fh->set_eof (); /* Flag that other end of pipe is gone */
select_printf ("%s, n %d", fh->get_name (), n);
if (s->except_selected)
- gotone += s->except_ready = TRUE;
+ gotone += s->except_ready = true;
if (s->read_selected)
- gotone += s->read_ready = TRUE;
+ gotone += s->read_ready = true;
}
if (n > 0 && s->read_selected)
{
select_printf ("%s, ready for read", fh->get_name ());
- gotone += s->read_ready = TRUE;
+ gotone += s->read_ready = true;
}
if (!gotone && s->fh->hit_eof ())
{
select_printf ("%s, saw EOF", fh->get_name ());
if (s->except_selected)
- gotone = s->except_ready = TRUE;
+ gotone = s->except_ready = true;
if (s->read_selected)
- gotone += s->read_ready = TRUE;
+ gotone += s->read_ready = true;
select_printf ("saw eof on '%s'", fh->get_name ());
}
@@ -490,35 +509,11 @@ out:
return gotone || s->write_ready;
}
-static int
-poll_pipe (select_record *me, fd_set *readfds, fd_set *writefds,
- fd_set *exceptfds)
-{
- return peek_pipe (me, 0) ?
- set_bits (me, readfds, writefds, exceptfds) :
- 0;
-}
-
-int
-fhandler_pipe::ready_for_read (int fd, DWORD howlong, int ignra)
-{
- select_record me (this);
- me.fd = fd;
- (void) select_read (&me);
- while (!peek_pipe (&me, ignra, guard) && howlong == INFINITE)
- if (fd >= 0 && cygheap->fdtab.not_open (fd))
- break;
- else if (WaitForSingleObject (signal_arrived, 10) == WAIT_OBJECT_0)
- break;
- select_printf ("returning %d", me.read_ready);
- return me.read_ready;
-}
-
static int start_thread_pipe (select_record *me, select_stuff *stuff);
struct pipeinf
{
- HANDLE thread;
+ cygthread *thread;
BOOL stop_thread_pipe;
select_record *start;
};
@@ -535,8 +530,8 @@ thread_pipe (void *arg)
while ((s = s->next))
if (s->startup == start_thread_pipe)
{
- if (peek_pipe (s, 0))
- gotone = TRUE;
+ if (peek_pipe (s, true))
+ gotone = true;
if (pi->stop_thread_pipe)
{
select_printf ("stopping");
@@ -562,13 +557,14 @@ start_thread_pipe (select_record *me, select_stuff *stuff)
{
if (stuff->device_specific[FHDEVN(FH_PIPE)])
{
- me->h = ((pipeinf *) stuff->device_specific[FHDEVN(FH_PIPE)])->thread;
+ me->h = *((pipeinf *) stuff->device_specific[FHDEVN(FH_PIPE)])->thread;
return 1;
}
pipeinf *pi = new pipeinf;
pi->start = &stuff->start;
pi->stop_thread_pipe = FALSE;
- pi->thread = me->h = makethread (thread_pipe, (LPVOID)pi, 0, "select_pipe");
+ pi->thread = new cygthread (thread_pipe, (LPVOID)pi, "select_pipe");
+ me->h = *pi->thread;
if (!me->h)
return 0;
stuff->device_specific[FHDEVN(FH_PIPE)] = (void *)pi;
@@ -581,9 +577,8 @@ pipe_cleanup (select_record *, select_stuff *stuff)
pipeinf *pi = (pipeinf *)stuff->device_specific[FHDEVN(FH_PIPE)];
if (pi && pi->thread)
{
- pi->stop_thread_pipe = TRUE;
- WaitForSingleObject (pi->thread, INFINITE);
- CloseHandle (pi->thread);
+ pi->stop_thread_pipe = true;
+ pi->thread->detach ();
delete pi;
stuff->device_specific[FHDEVN(FH_PIPE)] = NULL;
}
@@ -595,9 +590,10 @@ fhandler_pipe::select_read (select_record *s)
if (!s)
s = new select_record;
s->startup = start_thread_pipe;
- s->poll = poll_pipe;
+ s->peek = peek_pipe;
s->verify = verify_ok;
- s->read_selected = TRUE;
+ s->read_selected = true;
+ s->read_ready = false;
s->cleanup = pipe_cleanup;
return s;
}
@@ -609,11 +605,11 @@ fhandler_pipe::select_write (select_record *s)
{
s = new select_record;
s->startup = no_startup;
- s->poll = poll_pipe;
s->verify = no_verify;
}
- s->write_selected = TRUE;
- s->write_ready = TRUE;
+ s->peek = peek_pipe;
+ s->write_selected = true;
+ s->write_ready = true;
return s;
}
@@ -623,15 +619,16 @@ fhandler_pipe::select_except (select_record *s)
if (!s)
s = new select_record;
s->startup = start_thread_pipe;
- s->poll = poll_pipe;
+ s->peek = peek_pipe;
s->verify = verify_ok;
s->cleanup = pipe_cleanup;
- s->except_selected = TRUE;
+ s->except_selected = true;
+ s->except_ready = false;
return s;
}
static int
-peek_console (select_record *me, int ignra)
+peek_console (select_record *me, bool)
{
extern const char * get_nonascii_key (INPUT_RECORD& input_rec, char *);
fhandler_console *fh = (fhandler_console *)me->fh;
@@ -639,10 +636,10 @@ peek_console (select_record *me, int ignra)
if (!me->read_selected)
return me->write_ready;
- if (!ignra && fh->get_readahead_valid ())
+ if (fh->get_readahead_valid ())
{
select_printf ("readahead");
- return me->read_ready = 1;
+ return me->read_ready = true;
}
if (me->read_ready)
@@ -659,23 +656,27 @@ peek_console (select_record *me, int ignra)
for (;;)
if (fh->bg_check (SIGTTIN) <= bg_eof)
- return me->read_ready = 1;
+ return me->read_ready = true;
else if (!PeekConsoleInput (h, &irec, 1, &events_read) || !events_read)
break;
else
{
- if (irec.EventType == WINDOW_BUFFER_SIZE_EVENT)
- kill_pgrp (fh->tc->getpgid (), SIGWINCH);
- else if (irec.EventType == MOUSE_EVENT &&
- (irec.Event.MouseEvent.dwEventFlags == 0 ||
- irec.Event.MouseEvent.dwEventFlags == DOUBLE_CLICK))
+ if (irec.EventType == KEY_EVENT)
{
- if (fh->mouse_aware ())
- return me->read_ready = 1;
+ if (irec.Event.KeyEvent.bKeyDown
+ && (irec.Event.KeyEvent.uChar.AsciiChar
+ || get_nonascii_key (irec, tmpbuf)))
+ return me->read_ready = true;
+ }
+ else
+ {
+ fh->send_winch_maybe ();
+ if (irec.EventType == MOUSE_EVENT
+ && fh->mouse_aware ()
+ && (irec.Event.MouseEvent.dwEventFlags == 0
+ || irec.Event.MouseEvent.dwEventFlags == DOUBLE_CLICK))
+ return me->read_ready = true;
}
- else if (irec.EventType == KEY_EVENT && irec.Event.KeyEvent.bKeyDown == TRUE &&
- (irec.Event.KeyEvent.uChar.AsciiChar || get_nonascii_key (irec, tmpbuf)))
- return me->read_ready = 1;
/* Read and discard the event */
ReadConsoleInput (h, &irec, 1, &events_read);
@@ -685,15 +686,12 @@ peek_console (select_record *me, int ignra)
}
static int
-poll_console (select_record *me, fd_set *readfds, fd_set *writefds,
- fd_set *exceptfds)
+verify_console (select_record *me, fd_set *rfds, fd_set *wfds,
+ fd_set *efds)
{
- return peek_console (me, 0) ?
- set_bits (me, readfds, writefds, exceptfds) :
- 0;
+ return peek_console (me, true);
}
-MAKEready (console)
select_record *
fhandler_console::select_read (select_record *s)
@@ -702,13 +700,14 @@ fhandler_console::select_read (select_record *s)
{
s = new select_record;
s->startup = no_startup;
- s->poll = poll_console;
- s->verify = poll_console;
+ s->verify = verify_console;
set_cursor_maybe ();
}
+ s->peek = peek_console;
s->h = get_handle ();
- s->read_selected = TRUE;
+ s->read_selected = true;
+ s->read_ready = false;
return s;
}
@@ -719,13 +718,13 @@ fhandler_console::select_write (select_record *s)
{
s = new select_record;
s->startup = no_startup;
- s->poll = poll_console;
s->verify = no_verify;
set_cursor_maybe ();
}
- s->write_selected = TRUE;
- s->write_ready = TRUE;
+ s->peek = peek_console;
+ s->write_selected = true;
+ s->write_ready = true;
return s;
}
@@ -736,30 +735,16 @@ fhandler_console::select_except (select_record *s)
{
s = new select_record;
s->startup = no_startup;
- s->poll = poll_console;
s->verify = no_verify;
set_cursor_maybe ();
}
- s->except_selected = TRUE;
+ s->peek = peek_console;
+ s->except_selected = true;
+ s->except_ready = false;
return s;
}
-int
-fhandler_tty_common::ready_for_read (int fd, DWORD howlong, int ignra)
-{
- select_record me (this);
- me.fd = fd;
- (void) select_read (&me);
- while (!peek_pipe (&me, ignra) && howlong == INFINITE)
- if (fd >= 0 && cygheap->fdtab.not_open (fd))
- break;
- else if (WaitForSingleObject (signal_arrived, 10) == WAIT_OBJECT_0)
- break;
- select_printf ("returning %d", me.read_ready);
- return me.read_ready;
-}
-
select_record *
fhandler_tty_common::select_read (select_record *s)
{
@@ -783,7 +768,7 @@ verify_tty_slave (select_record *me, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds)
{
if (WaitForSingleObject (me->h, 0) == WAIT_OBJECT_0)
- me->read_ready = 1;
+ me->read_ready = true;
return set_bits (me, readfds, writefds, exceptfds);
}
@@ -794,37 +779,14 @@ fhandler_tty_slave::select_read (select_record *s)
s = new select_record;
s->h = input_available_event;
s->startup = no_startup;
- s->poll = poll_pipe;
+ s->peek = peek_pipe;
s->verify = verify_tty_slave;
- s->read_selected = TRUE;
+ s->read_selected = true;
+ s->read_ready = false;
s->cleanup = NULL;
return s;
}
-int
-fhandler_tty_slave::ready_for_read (int fd, DWORD howlong, int ignra)
-{
- HANDLE w4[2];
- if (!ignra && get_readahead_valid ())
- {
- select_printf ("readahead");
- return 1;
- }
- w4[0] = signal_arrived;
- w4[1] = input_available_event;
- switch (WaitForMultipleObjects (2, w4, FALSE, howlong))
- {
- case WAIT_OBJECT_0 + 1:
- return 1;
- case WAIT_FAILED:
- select_printf ("wait failed %E");
- case WAIT_OBJECT_0:
- case WAIT_TIMEOUT:
- default:
- return 0;
- }
-}
-
select_record *
fhandler_dev_null::select_read (select_record *s)
{
@@ -832,12 +794,11 @@ fhandler_dev_null::select_read (select_record *s)
{
s = new select_record;
s->startup = no_startup;
- s->poll = set_bits;
s->verify = no_verify;
}
s->h = get_handle ();
- s->read_selected = TRUE;
- s->read_ready = TRUE;
+ s->read_selected = true;
+ s->read_ready = true;
return s;
}
@@ -848,12 +809,11 @@ fhandler_dev_null::select_write (select_record *s)
{
s = new select_record;
s->startup = no_startup;
- s->poll = set_bits;
s->verify = no_verify;
}
s->h = get_handle ();
- s->write_selected = TRUE;
- s->write_ready = TRUE;
+ s->write_selected = true;
+ s->write_ready = true;
return s;
}
@@ -864,12 +824,11 @@ fhandler_dev_null::select_except (select_record *s)
{
s = new select_record;
s->startup = no_startup;
- s->poll = set_bits;
s->verify = no_verify;
}
s->h = get_handle ();
- s->except_selected = TRUE;
- s->except_ready = TRUE;
+ s->except_selected = true;
+ s->except_ready = true;
return s;
}
@@ -877,21 +836,20 @@ static int start_thread_serial (select_record *me, select_stuff *stuff);
struct serialinf
{
- HANDLE thread;
+ cygthread *thread;
BOOL stop_thread_serial;
select_record *start;
};
static int
-peek_serial (select_record *s, int)
+peek_serial (select_record *s, bool)
{
- DWORD ev;
COMSTAT st;
fhandler_serial *fh = (fhandler_serial *)s->fh;
if (fh->get_readahead_valid () || fh->overlapped_armed < 0)
- return s->read_ready = 1;
+ return s->read_ready = true;
select_printf ("fh->overlapped_armed %d", fh->overlapped_armed);
@@ -910,20 +868,19 @@ peek_serial (select_record *s, int)
if (!fh->overlapped_armed)
{
- DWORD ev;
COMSTAT st;
ResetEvent (fh->io_status.hEvent);
- if (!ClearCommError (h, &ev, &st))
+ if (!ClearCommError (h, &fh->ev, &st))
{
debug_printf ("ClearCommError");
goto err;
}
else if (st.cbInQue)
- return s->read_ready = 1;
- else if (WaitCommEvent (h, &ev, &fh->io_status))
- return s->read_ready = 1;
+ return s->read_ready = true;
+ else if (WaitCommEvent (h, &fh->ev, &fh->io_status))
+ return s->read_ready = true;
else if (GetLastError () == ERROR_IO_PENDING)
fh->overlapped_armed = 1;
else
@@ -943,7 +900,7 @@ peek_serial (select_record *s, int)
switch (WaitForMultipleObjects (2, w4, FALSE, to))
{
case WAIT_OBJECT_0:
- if (!ClearCommError (h, &ev, &st))
+ if (!ClearCommError (h, &fh->ev, &st))
{
debug_printf ("ClearCommError");
goto err;
@@ -952,7 +909,7 @@ peek_serial (select_record *s, int)
Sleep (to);
else
{
- return s->read_ready = 1;
+ return s->read_ready = true;
select_printf ("got something");
}
PurgeComm (h, PURGE_TXABORT | PURGE_RXABORT);
@@ -983,7 +940,7 @@ err:
}
__seterrno ();
- s->saw_error = TRUE;
+ s->saw_error = true;
select_printf ("error %E");
return -1;
}
@@ -1000,8 +957,8 @@ thread_serial (void *arg)
while ((s = s->next))
if (s->startup == start_thread_serial)
{
- if (peek_serial (s, 0))
- gotone = TRUE;
+ if (peek_serial (s, true))
+ gotone = true;
}
if (si->stop_thread_serial)
{
@@ -1021,15 +978,14 @@ start_thread_serial (select_record *me, select_stuff *stuff)
{
if (stuff->device_specific[FHDEVN(FH_SERIAL)])
{
- me->h = ((pipeinf *) stuff->device_specific[FHDEVN(FH_SERIAL)])->thread;
+ me->h = *((serialinf *) stuff->device_specific[FHDEVN(FH_SERIAL)])->thread;
return 1;
}
serialinf *si = new serialinf;
si->start = &stuff->start;
si->stop_thread_serial = FALSE;
- si->thread = me->h = makethread (thread_serial, (LPVOID)si, 0, "select_serial");
- if (!me->h)
- return 0;
+ si->thread = new cygthread (thread_serial, (LPVOID)si, "select_serial");
+ me->h = *si->thread;
stuff->device_specific[FHDEVN(FH_SERIAL)] = (void *)si;
return 1;
}
@@ -1040,26 +996,13 @@ serial_cleanup (select_record *, select_stuff *stuff)
serialinf *si = (serialinf *)stuff->device_specific[FHDEVN(FH_SERIAL)];
if (si && si->thread)
{
- si->stop_thread_serial = TRUE;
- WaitForSingleObject (si->thread, INFINITE);
- CloseHandle (si->thread);
+ si->stop_thread_serial = true;
+ si->thread->detach ();
delete si;
stuff->device_specific[FHDEVN(FH_SERIAL)] = NULL;
}
}
-static int
-poll_serial (select_record *me, fd_set *readfds, fd_set *writefds,
- fd_set *exceptfds)
-
-{
- return peek_serial (me, 0) ?
- set_bits (me, readfds, writefds, exceptfds) :
- 0;
-}
-
-MAKEready (serial)
-
select_record *
fhandler_serial::select_read (select_record *s)
{
@@ -1067,11 +1010,12 @@ fhandler_serial::select_read (select_record *s)
{
s = new select_record;
s->startup = start_thread_serial;
- s->poll = poll_serial;
s->verify = verify_ok;
s->cleanup = serial_cleanup;
}
- s->read_selected = TRUE;
+ s->peek = peek_serial;
+ s->read_selected = true;
+ s->read_ready = false;
return s;
}
@@ -1082,12 +1026,12 @@ fhandler_serial::select_write (select_record *s)
{
s = new select_record;
s->startup = no_startup;
- s->poll = set_bits;
s->verify = verify_ok;
}
+ s->peek = peek_serial;
s->h = get_handle ();
- s->write_selected = TRUE;
- s->write_ready = TRUE;
+ s->write_selected = true;
+ s->write_ready = true;
return s;
}
@@ -1098,18 +1042,53 @@ fhandler_serial::select_except (select_record *s)
{
s = new select_record;
s->startup = no_startup;
- s->poll = set_bits;
s->verify = verify_ok;
}
s->h = NULL;
- s->except_selected = FALSE; // Can't do this
+ s->peek = peek_serial;
+ s->except_selected = false; // Can't do this
+ s->except_ready = false;
return s;
}
int
-fhandler_base::ready_for_read (int, DWORD, int)
+fhandler_base::ready_for_read (int fd, DWORD howlong)
{
- return 1;
+ int avail = 0;
+ select_record me (this);
+ me.fd = fd;
+ while (!avail)
+ {
+ (void) select_read (&me);
+ avail = me.read_ready ?: me.peek (&me, false);
+
+ if (fd >= 0 && cygheap->fdtab.not_open (fd))
+ {
+ set_sig_errno (EBADF);
+ avail = 0;
+ break;
+ }
+
+ if (howlong != INFINITE)
+ {
+ if (!avail)
+ set_sig_errno (EAGAIN);
+ break;
+ }
+
+ if (WaitForSingleObject (signal_arrived, avail ? 0 : 10) == WAIT_OBJECT_0)
+ {
+ set_sig_errno (EINTR);
+ avail = 0;
+ break;
+ }
+ }
+
+ if (get_guard () && !avail && me.read_ready)
+ ReleaseMutex (get_guard ());
+
+ select_printf ("read_ready %d, avail %d", me.read_ready, avail);
+ return avail;
}
select_record *
@@ -1119,12 +1098,11 @@ fhandler_base::select_read (select_record *s)
{
s = new select_record;
s->startup = no_startup;
- s->poll = set_bits;
s->verify = verify_ok;
}
s->h = get_handle ();
- s->read_selected = TRUE;
- s->read_ready = TRUE;
+ s->read_selected = true;
+ s->read_ready = true;
return s;
}
@@ -1135,12 +1113,11 @@ fhandler_base::select_write (select_record *s)
{
s = new select_record;
s->startup = no_startup;
- s->poll = set_bits;
s->verify = verify_ok;
}
s->h = get_handle ();
- s->write_selected = TRUE;
- s->write_ready = TRUE;
+ s->write_selected = true;
+ s->write_ready = true;
return s;
}
@@ -1151,17 +1128,17 @@ fhandler_base::select_except (select_record *s)
{
s = new select_record;
s->startup = no_startup;
- s->poll = set_bits;
s->verify = verify_ok;
}
s->h = NULL;
- s->write_selected = TRUE;
+ s->except_selected = true;
+ s->except_ready = false;
return s;
}
struct socketinf
{
- HANDLE thread;
+ cygthread *thread;
winsock_fd_set readfds, writefds, exceptfds;
SOCKET exitsock;
struct sockaddr_in sin;
@@ -1169,65 +1146,59 @@ struct socketinf
};
static int
-peek_socket (select_record *me, int)
+peek_socket (select_record *me, bool)
{
winsock_fd_set ws_readfds, ws_writefds, ws_exceptfds;
struct timeval tv = {0, 0};
WINSOCK_FD_ZERO (&ws_readfds);
WINSOCK_FD_ZERO (&ws_writefds);
WINSOCK_FD_ZERO (&ws_exceptfds);
- int gotone = 0;
HANDLE h;
set_handle_or_return_if_not_open (h, me);
select_printf ("considering handle %p", h);
- if (me->read_selected)
+ if (me->read_selected && !me->read_ready)
{
select_printf ("adding read fd_set %s, fd %d", me->fh->get_name (),
me->fd);
WINSOCK_FD_SET (h, &ws_readfds);
}
- if (me->write_selected)
+ if (me->write_selected && !me->write_ready)
{
select_printf ("adding write fd_set %s, fd %d", me->fh->get_name (),
me->fd);
WINSOCK_FD_SET (h, &ws_writefds);
}
- if (me->except_selected)
+ if ((me->except_selected || me->except_on_write) && !me->except_ready)
{
select_printf ("adding except fd_set %s, fd %d", me->fh->get_name (),
me->fd);
WINSOCK_FD_SET (h, &ws_exceptfds);
}
- int r = WINSOCK_SELECT (0, &ws_readfds, &ws_writefds, &ws_exceptfds, &tv);
- select_printf ("WINSOCK_SELECT returned %d", r);
- if (r == -1)
+ int r;
+ if ((me->read_selected && !me->read_ready)
+ || (me->write_selected && !me->write_ready)
+ || ((me->except_selected || me->except_on_write) && !me->except_ready))
{
- select_printf ("error %d", WSAGetLastError ());
- return 0;
+ r = WINSOCK_SELECT (0, &ws_readfds, &ws_writefds, &ws_exceptfds, &tv);
+ select_printf ("WINSOCK_SELECT returned %d", r);
+ if (r == -1)
+ {
+ select_printf ("error %d", WSAGetLastError ());
+ set_winsock_errno ();
+ return 0;
+ }
+ if (WINSOCK_FD_ISSET (h, &ws_readfds) || (me->read_selected && me->read_ready))
+ me->read_ready = true;
+ if (WINSOCK_FD_ISSET (h, &ws_writefds) || (me->write_selected && me->write_ready))
+ me->write_ready = true;
+ if (WINSOCK_FD_ISSET (h, &ws_exceptfds) || ((me->except_selected || me->except_on_write) && me->except_ready))
+ me->except_ready = true;
}
-
- if (WINSOCK_FD_ISSET (h, &ws_readfds) || (me->read_selected && me->read_ready))
- gotone = me->read_ready = TRUE;
- if (WINSOCK_FD_ISSET (h, &ws_writefds) || (me->write_selected && me->write_ready))
- gotone = me->write_ready = TRUE;
- if (WINSOCK_FD_ISSET (h, &ws_exceptfds) || (me->except_selected && me->except_ready))
- gotone = me->except_ready = TRUE;
- return gotone;
-}
-
-static int
-poll_socket (select_record *me, fd_set *readfds, fd_set *writefds,
- fd_set *exceptfds)
-{
- return peek_socket (me, 0) ?
- set_bits (me, readfds, writefds, exceptfds) :
- 0;
+ return me->read_ready || me->write_ready || me->except_ready;
}
-MAKEready (socket)
-
static int start_thread_socket (select_record *, select_stuff *);
static DWORD WINAPI
@@ -1249,17 +1220,17 @@ thread_socket (void *arg)
if (WINSOCK_FD_ISSET (h, &si->readfds))
{
select_printf ("read_ready");
- s->read_ready = TRUE;
+ s->read_ready = true;
}
if (WINSOCK_FD_ISSET (h, &si->writefds))
{
select_printf ("write_ready");
- s->write_ready = TRUE;
+ s->write_ready = true;
}
if (WINSOCK_FD_ISSET (h, &si->exceptfds))
{
select_printf ("except_ready");
- s->except_ready = TRUE;
+ s->except_ready = true;
}
}
@@ -1278,7 +1249,7 @@ start_thread_socket (select_record *me, select_stuff *stuff)
if ((si = (socketinf *)stuff->device_specific[FHDEVN(FH_SOCKET)]))
{
- me->h = si->thread;
+ me->h = *si->thread;
return 1;
}
@@ -1292,17 +1263,17 @@ start_thread_socket (select_record *me, select_stuff *stuff)
{
HANDLE h = s->fh->get_handle ();
select_printf ("Handle %p", h);
- if (s->read_selected)
+ if (s->read_selected && !s->read_ready)
{
WINSOCK_FD_SET (h, &si->readfds);
select_printf ("Added to readfds");
}
- if (s->write_selected)
+ if (s->write_selected && !s->write_ready)
{
WINSOCK_FD_SET (h, &si->writefds);
select_printf ("Added to writefds");
}
- if (s->except_selected)
+ if ((s->except_selected || s->except_on_write) && !s->except_ready)
{
WINSOCK_FD_SET (h, &si->exceptfds);
select_printf ("Added to exceptfds");
@@ -1319,7 +1290,7 @@ start_thread_socket (select_record *me, select_stuff *stuff)
int tmp = 1;
(void) setsockopt (si->exitsock, SOL_SOCKET, SO_REUSEADDR, (char *) &tmp, sizeof (tmp));
- int sin_len = sizeof(si->sin);
+ int sin_len = sizeof (si->sin);
memset (&si->sin, 0, sizeof (si->sin));
si->sin.sin_family = AF_INET;
si->sin.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
@@ -1347,9 +1318,9 @@ start_thread_socket (select_record *me, select_stuff *stuff)
stuff->device_specific[FHDEVN(FH_SOCKET)] = (void *) si;
si->start = &stuff->start;
select_printf ("stuff_start %p", &stuff->start);
- si->thread = me->h = makethread (thread_socket, (LPVOID)si, 0,
- "select_socket");
- return !!me->h;
+ si->thread = new cygthread (thread_socket, (LPVOID)si, "select_socket");
+ me->h = *si->thread;
+ return 1;
err:
set_winsock_errno ();
@@ -1369,8 +1340,8 @@ socket_cleanup (select_record *, select_stuff *stuff)
/* Set LINGER with 0 timeout for hard close */
struct linger tmp = {1, 0}; /* On, 0 delay */
- (void) setsockopt (s, SOL_SOCKET, SO_LINGER, (char *)&tmp, sizeof(tmp));
- (void) setsockopt (si->exitsock, SOL_SOCKET, SO_LINGER, (char *)&tmp, sizeof(tmp));
+ (void) setsockopt (s, SOL_SOCKET, SO_LINGER, (char *)&tmp, sizeof (tmp));
+ (void) setsockopt (si->exitsock, SOL_SOCKET, SO_LINGER, (char *)&tmp, sizeof (tmp));
/* Connecting to si->exitsock will cause any executing select to wake
up. When this happens then the exitsock condition will cause the
@@ -1385,10 +1356,9 @@ socket_cleanup (select_record *, select_stuff *stuff)
closesocket (s);
/* Wait for thread to go away */
- WaitForSingleObject (si->thread, INFINITE);
+ si->thread->detach ();
shutdown (si->exitsock, SD_BOTH);
closesocket (si->exitsock);
- CloseHandle (si->thread);
stuff->device_specific[FHDEVN(FH_SOCKET)] = NULL;
delete si;
}
@@ -1402,12 +1372,12 @@ fhandler_socket::select_read (select_record *s)
{
s = new select_record;
s->startup = start_thread_socket;
- s->poll = poll_socket;
s->verify = verify_true;
s->cleanup = socket_cleanup;
}
+ s->peek = peek_socket;
s->read_ready = saw_shutdown_read ();
- s->read_selected = TRUE;
+ s->read_selected = true;
return s;
}
@@ -1418,12 +1388,17 @@ fhandler_socket::select_write (select_record *s)
{
s = new select_record;
s->startup = start_thread_socket;
- s->poll = poll_socket;
s->verify = verify_true;
s->cleanup = socket_cleanup;
}
- s->write_ready = saw_shutdown_write ();
- s->write_selected = TRUE;
+ s->peek = peek_socket;
+ s->write_ready = saw_shutdown_write () || is_unconnected ();
+ s->write_selected = true;
+ if (is_connect_pending ())
+ {
+ s->except_ready = saw_shutdown_write () || saw_shutdown_read ();
+ s->except_on_write = true;
+ }
return s;
}
@@ -1434,18 +1409,18 @@ fhandler_socket::select_except (select_record *s)
{
s = new select_record;
s->startup = start_thread_socket;
- s->poll = poll_socket;
s->verify = verify_true;
s->cleanup = socket_cleanup;
}
+ s->peek = peek_socket;
/* FIXME: Is this right? Should these be used as criteria for except? */
s->except_ready = saw_shutdown_write () || saw_shutdown_read ();
- s->except_selected = TRUE;
+ s->except_selected = true;
return s;
}
static int
-peek_windows (select_record *me, int)
+peek_windows (select_record *me, bool)
{
MSG m;
HANDLE h;
@@ -1456,7 +1431,7 @@ peek_windows (select_record *me, int)
if (PeekMessage (&m, (HWND) h, 0, 0, PM_NOREMOVE))
{
- me->read_ready = TRUE;
+ me->read_ready = true;
select_printf ("window %d(%p) ready", me->fd, me->fh->get_handle ());
return 1;
}
@@ -1466,17 +1441,12 @@ peek_windows (select_record *me, int)
}
static int
-poll_windows (select_record *me, fd_set *readfds, fd_set *writefds,
- fd_set *exceptfds)
+verify_windows (select_record *me, fd_set *rfds, fd_set *wfds,
+ fd_set *efds)
{
-
- return peek_windows (me, 0) ?
- set_bits (me, readfds, writefds, exceptfds) :
- 0;
+ return peek_windows (me, true);
}
-MAKEready (windows)
-
select_record *
fhandler_windows::select_read (select_record *s)
{
@@ -1484,13 +1454,13 @@ fhandler_windows::select_read (select_record *s)
{
s = new select_record;
s->startup = no_startup;
- s->poll = poll_windows;
- s->verify = poll_windows;
}
+ s->verify = verify_windows;
+ s->peek = peek_windows;
+ s->read_selected = true;
+ s->read_ready = false;
s->h = get_handle ();
- s->read_selected = TRUE;
- s->h = get_handle ();
- s->windows_handle = TRUE;
+ s->windows_handle = true;
return s;
}
@@ -1501,13 +1471,13 @@ fhandler_windows::select_write (select_record *s)
{
s = new select_record;
s->startup = no_startup;
- s->poll = set_bits;
s->verify = verify_ok;
}
+ s->peek = peek_windows;
s->h = get_handle ();
- s->write_selected = TRUE;
- s->write_ready = TRUE;
- s->windows_handle = TRUE;
+ s->write_selected = true;
+ s->write_ready = true;
+ s->windows_handle = true;
return s;
}
@@ -1518,12 +1488,12 @@ fhandler_windows::select_except (select_record *s)
{
s = new select_record;
s->startup = no_startup;
- s->poll = set_bits;
s->verify = verify_ok;
}
+ s->peek = peek_windows;
s->h = get_handle ();
- s->except_selected = TRUE;
- s->except_ready = TRUE;
- s->windows_handle = TRUE;
+ s->except_selected = true;
+ s->except_ready = true;
+ s->windows_handle = true;
return s;
}