newlib-cygwin/winsup/cygwin/select.cc

1537 lines
35 KiB
C++
Raw Normal View History

2000-02-18 03:38:33 +08:00
/* select.cc
2001-03-18 11:34:05 +08:00
Copyright 1996, 1997, 1998, 1999, 2000, 2001 Red Hat, Inc.
2000-02-18 03:38:33 +08:00
Written by Christopher Faylor of Cygnus Solutions
cgf@cygnus.com
This file is part of Cygwin.
This software is a copyrighted work licensed under the terms of the
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
/*
* The following line means that the BSD socket
* definitions for fd_set, FD_ISSET etc. are used in this
* file.
*/
#define __INSIDE_CYGWIN_NET__
#include "winsup.h"
2000-02-18 03:38:33 +08:00
#include <errno.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <sys/time.h>
#include <wingdi.h>
#include <winuser.h>
2000-02-18 03:38:33 +08:00
#include <netdb.h>
#include <unistd.h>
#include <stdio.h>
#define USE_SYS_TYPES_FD_SET
2000-02-18 03:38:33 +08:00
#include <winsock.h>
#include "select.h"
#include "cygerrno.h"
#include "security.h"
#include "fhandler.h"
Add "path.h" include throughout, where needed. Use new path_conv methods and operators to simplify testing for directory and attributes, throughout. * path.h (path_conv::exists): New method. (path_conv::has_attribute): Ditto. (path_conv::isdir): Ditto. (path_conv::DWORD &): New operator. (path_conv::int &): Ditto. * dir.cc (rmdir): Eliminate a goto. * dtable.cc (dtable::build_fhandler): Accept opt and suffix info for path_conv.check. Return fh == NULL on path_conv error. Pass unit to set_name as appropriate. (dtable::reset_unix_path_name): New method. * dtable.h (dtable): Declare new method. Reflect arg changes to build_fhandler. * fhandler.cc (fhandler_disk_dummy_name): Eliminate. (fhandler_base::set_name): Expect paths to be NULL. Build unix_path_name from win32_path_name when it is a device. (fhandler_base::reset_unix_path_name): New method. (fhandler_base::raw_read): Report EISDIR when ERROR_INVALID_FUNCTION or ERROR_INVALID_PARAMETER and reading a directory. (fhandler_disk_file::fstat): Don't call stat_dev since we should now never be calling fhandler_disk_file methods with devices. (fhandler_base::fhandler_base): Clear {unix,win32}_path_name. (fhandler_base::~fhandler_base): Always free {unix,win32}_path_name. (fhandler_disk_file::fhandler_disk_file): Remove set_no_free_names kludge. (fhandler_disk_file::open): Ditto. * fhandler.h (fhandler_base::no_free_names): Eliminate. (fhandler_base::set_no_free_names): Ditto. * fhandler_tty.cc (fhandler_tty_slave::fhandler_tty_slave): Don't set unix_path_name here. * path.cc (fchdir): Lock fd table throughout. Use new dtable::reset_unix_path_name method to reset path. * syscalls.cc (stat_worker): Reorganize to always call fstat method. Pass path_conv method to fhandler_*::open. (chroot): Elminate a goto.
2001-10-01 12:10:07 +08:00
#include "path.h"
#include "dtable.h"
#include "cygheap.h"
#include "sync.h"
#include "sigproc.h"
#include "perthread.h"
#include "tty.h"
2000-02-18 03:38:33 +08:00
/*
* All these defines below should be in sys/types.h
* but because of the includes above, they may not have
* been included. We create special UNIX_xxxx versions here.
*/
#ifndef NBBY
#define NBBY 8 /* number of bits in a byte */
#endif /* NBBY */
/*
* Select uses bit masks of file descriptors in longs.
* These macros manipulate such bit fields (the filesystem macros use chars).
* FD_SETSIZE may be defined by the user, but the default here
* should be >= NOFILE (param.h).
*/
typedef long fd_mask;
#define UNIX_NFDBITS (sizeof (fd_mask) * NBBY) /* bits per mask */
#ifndef unix_howmany
#define unix_howmany(x,y) (((x)+((y)-1))/(y))
#endif
#define unix_fd_set fd_set
#define NULL_fd_set ((fd_set *) NULL)
2000-02-18 03:38:33 +08:00
#define sizeof_fd_set(n) \
((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) \
((p)->fds_bits[(n)/UNIX_NFDBITS] &= ~(1L << ((n) % UNIX_NFDBITS)))
#define UNIX_FD_ISSET(n, p) \
((p)->fds_bits[(n)/UNIX_NFDBITS] & (1L << ((n) % UNIX_NFDBITS)))
#define UNIX_FD_ZERO(p, n) \
bzero ((caddr_t)(p), sizeof_fd_set ((n)))
#define allocfd_set(n) ((fd_set *) memset (alloca (sizeof_fd_set (n)), 0, sizeof_fd_set (n)))
2000-02-18 03:38:33 +08:00
#define copyfd_set(to, from, n) memcpy (to, from, sizeof_fd_set (n));
#define set_handle_or_return_if_not_open(h, s) \
h = (s)->fh->get_handle (); \
if (cygheap->fdtab.not_open ((s)->fd)) \
2000-02-18 03:38:33 +08:00
{ \
(s)->saw_error = TRUE; \
set_errno (EBADF); \
return -1; \
} \
/* The main select code.
*/
extern "C"
int
cygwin_select (int maxfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
struct timeval *to)
2000-02-18 03:38:33 +08:00
{
select_stuff sel;
fd_set *dummy_readfds = allocfd_set (maxfds);
fd_set *dummy_writefds = allocfd_set (maxfds);
fd_set *dummy_exceptfds = allocfd_set (maxfds);
sigframe thisframe (mainthread);
2000-02-18 03:38:33 +08:00
select_printf ("%d, %p, %p, %p, %p", maxfds, readfds, writefds, exceptfds, to);
2000-02-18 03:38:33 +08:00
if (!readfds)
readfds = dummy_readfds;
2000-02-18 03:38:33 +08:00
if (!writefds)
writefds = dummy_writefds;
2000-02-18 03:38:33 +08:00
if (!exceptfds)
exceptfds = dummy_exceptfds;
2000-02-18 03:38:33 +08:00
for (int i = 0; i < maxfds; i++)
2000-02-18 03:38:33 +08:00
if (!sel.test_and_set (i, readfds, writefds, exceptfds))
{
select_printf ("aborting due to test_and_set error");
return -1; /* Invalid fd, maybe? */
}
/* Convert to milliseconds or INFINITE if to == NULL */
DWORD ms = to ? (to->tv_sec * 1000) + (to->tv_usec / 1000) : INFINITE;
if (ms == 0 && to->tv_usec)
ms = 1; /* At least 1 ms granularity */
if (to)
select_printf ("to->tv_sec %d, to->tv_usec %d, ms %d", to->tv_sec, to->tv_usec, ms);
else
select_printf ("to NULL, ms %x", ms);
select_printf ("sel.always_ready %d", sel.always_ready);
2000-02-18 03:38:33 +08:00
int timeout = 0;
/* Allocate some fd_set structures using the number of fds as a guide. */
fd_set *r = allocfd_set (maxfds);
fd_set *w = allocfd_set (maxfds);
fd_set *e = allocfd_set (maxfds);
2000-02-18 03:38:33 +08:00
/* Degenerate case. No fds to wait for. Just wait. */
if (sel.start.next == NULL)
2000-02-18 03:38:33 +08:00
{
2001-08-29 04:39:22 +08:00
if (WaitForSingleObject (signal_arrived, ms) == WAIT_OBJECT_0)
2000-02-18 03:38:33 +08:00
{
select_printf ("signal received");
set_sig_errno (EINTR);
return -1;
}
timeout = 1;
2000-02-18 03:38:33 +08:00
}
else if (sel.always_ready || ms == 0)
/* Don't bother waiting. */;
else if ((timeout = sel.wait (r, w, e, ms) < 0))
return -1; /* some kind of error */
sel.cleanup ();
copyfd_set (readfds, r, maxfds);
copyfd_set (writefds, w, maxfds);
copyfd_set (exceptfds, e, maxfds);
return timeout ? 0 : sel.poll (readfds, writefds, exceptfds);
2000-02-18 03:38:33 +08:00
}
/* Call cleanup functions for all inspected fds. Gets rid of any
executing threads. */
void
select_stuff::cleanup ()
2000-02-18 03:38:33 +08:00
{
select_record *s = &start;
select_printf ("calling cleanup routines");
while ((s = s->next))
if (s->cleanup)
{
s->cleanup (s, this);
s->cleanup = NULL;
}
}
2000-02-18 03:38:33 +08:00
/* Destroy all storage associated with select stuff. */
select_stuff::~select_stuff ()
{
cleanup ();
select_record *s = &start;
2000-02-18 03:38:33 +08:00
select_record *snext = start.next;
select_printf ("deleting select records");
while ((s = snext))
{
snext = s->next;
delete s;
}
}
/* Add a record to the select chain */
int
select_stuff::test_and_set (int i, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds)
{
select_record *s = NULL;
if (UNIX_FD_ISSET (i, readfds) && (s = cygheap->fdtab.select_read (i, s)) == NULL)
2000-02-18 03:38:33 +08:00
return 0; /* error */
if (UNIX_FD_ISSET (i, writefds) && (s = cygheap->fdtab.select_write (i, s)) == NULL)
2000-02-18 03:38:33 +08:00
return 0; /* error */
if (UNIX_FD_ISSET (i, exceptfds) && (s = cygheap->fdtab.select_except (i, s)) == NULL)
2000-02-18 03:38:33 +08:00
return 0; /* error */
if (s == NULL)
return 1; /* nothing to do */
if (s->read_ready || s->write_ready || s->except_ready)
always_ready = TRUE;
if (s->windows_handle || s->windows_handle || s->windows_handle)
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,
DWORD ms)
{
int wait_ret;
HANDLE w4[MAXIMUM_WAIT_OBJECTS];
2000-02-18 03:38:33 +08:00
select_record *s = &start;
int m = 0;
int res = 0;
2000-02-18 03:38:33 +08:00
w4[m++] = signal_arrived; /* Always wait for the arrival of a signal. */
/* Loop through the select chain, starting up anything appropriate and
counting the number of active fds. */
while ((s = s->next))
{
if (m > MAXIMUM_WAIT_OBJECTS)
{
set_errno (EINVAL);
return -1;
}
2000-02-18 03:38:33 +08:00
if (!s->startup (s, this))
{
__seterrno ();
return -1;
}
if (s->h == NULL)
continue;
for (int i = 1; i < m; i++)
if (w4[i] == s->h)
goto next_while;
w4[m++] = s->h;
next_while:
continue;
}
DWORD start_time = GetTickCount (); /* Record the current time for later use. */
debug_printf ("m %d, ms %u", m, ms);
2000-02-18 03:38:33 +08:00
for (;;)
{
if (!windows_used)
wait_ret = WaitForMultipleObjects (m, w4, FALSE, ms);
else
wait_ret = MsgWaitForMultipleObjects (m, w4, FALSE, ms, QS_ALLINPUT);
switch (wait_ret)
{
case WAIT_OBJECT_0:
select_printf ("signal received");
set_sig_errno (EINTR);
return -1;
case WAIT_FAILED:
select_printf ("WaitForMultipleObjects failed");
__seterrno ();
return -1;
case WAIT_TIMEOUT:
select_printf ("timed out");
res = 1;
2000-02-18 03:38:33 +08:00
goto out;
}
select_printf ("woke up. wait_ret %d. verifying", wait_ret);
s = &start;
int gotone = FALSE;
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))
2000-02-18 03:38:33 +08:00
gotone = TRUE;
select_printf ("gotone %d", gotone);
if (gotone)
goto out;
if (ms == INFINITE)
{
select_printf ("looping");
continue;
}
select_printf ("recalculating ms");
DWORD now = GetTickCount ();
if (now > (start_time + ms))
{
select_printf ("timed out after verification");
goto out;
}
ms -= (now - start_time);
start_time = now;
select_printf ("ms now %u", ms);
}
out:
select_printf ("returning %d", res);
return res;
2000-02-18 03:38:33 +08:00
}
static int
set_bits (select_record *me, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds)
2000-02-18 03:38:33 +08:00
{
int ready = 0;
select_printf ("me %p, testing fd %d (%s)", me, me->fd, me->fh->get_name ());
if (me->read_selected && me->read_ready)
{
UNIX_FD_SET (me->fd, readfds);
ready++;
}
if (me->write_selected && me->write_ready)
{
UNIX_FD_SET (me->fd, writefds);
ready++;
}
if (me->except_ready && me->except_ready)
{
UNIX_FD_SET (me->fd, exceptfds);
ready++;
}
select_printf ("ready %d", ready);
return ready;
}
static int
verify_true (select_record *, fd_set *, fd_set *, fd_set *)
2000-02-18 03:38:33 +08:00
{
return 1;
}
static int
verify_ok (select_record *me, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds)
{
return set_bits (me, readfds, writefds, exceptfds);
}
static int
no_startup (select_record *, select_stuff *)
2000-02-18 03:38:33 +08:00
{
return 1;
}
static int
no_verify (select_record *, fd_set *, fd_set *, fd_set *)
{
return 0;
}
static int
* dtable.cc (dtable::build_fhandler): Issue internal error on unknown device. * fhandler.cc (fhandler_base::close): Show both name and handle in debugging output. * fhandler.h (fhandler_base::get_guard): New virtual method. (fhandler_pipe::get_guard): New method. (fhandler_socket::ready_for_read): Delete declaration. (fhandler_pipe::ready_for_read): Ditto. (fhandler_serial::ready_for_read): Ditto. (fhandler_console::ready_for_read): Ditto. (fhandler_tty_common::ready_for_read): Ditto. (fhandler_windows::ready_for_read): Ditto. (struct select_record::peek): Declare new method. * select.cc (MAKEready): Delete. (peek_pipe): Use get_guard method to retrieve potential guard mutex handle. (fhandler_base::ready_for_read): Rewrite as generic ready-for-read handler. Should only be called for "slow" devices. (fhandler_socket::ready_for_read): Delete definition. (fhandler_pipe::ready_for_read): Ditto. (fhandler_serial::ready_for_read): Ditto. (fhandler_console::ready_for_read): Ditto. (fhandler_tty_common::ready_for_read): Ditto. (fhandler_windows::ready_for_read): Ditto. (fhandler_pipe::select_read): Fill in new peek record in select_record structure. (fhandler_console::select_read): Ditto. (fhandler_tty_common::select_read): Ditto. (fhandler_serial::select_read): Ditto. (fhandler_socket::select_read): Ditto. (fhandler_socket::select_read): Ditto. (fhandler_tty_slave::ready_for_read): Check for tty not open. Set errnos appropriately. * syscalls.cc (_read): Allow ready_for_read to set errno. * pinfo.cc (pinfo::init): Return spawn/NO_WAIT process as valid if it is initializing. * sigproc.cc (getsem): Adjust wait for process to initialize downward to avoid huge waits.
2001-11-02 05:15:53 +08:00
peek_pipe (select_record *s, int ignra)
2000-02-18 03:38:33 +08:00
{
int n = 0;
int gotone = 0;
fhandler_base *fh = s->fh;
HANDLE h;
HANDLE guard_mutex = fh->get_guard ();
2000-02-18 03:38:33 +08:00
set_handle_or_return_if_not_open (h, s);
/* Don't perform complicated tests if we don't need to. */
if (!s->read_selected && !s->except_selected)
goto out;
if (s->read_selected)
2000-02-18 03:38:33 +08:00
{
if (s->read_ready)
{
select_printf ("already ready");
gotone = 1;
goto out;
}
2000-02-18 03:38:33 +08:00
switch (fh->get_device ())
{
case FH_PTYM:
case FH_TTYM:
if (((fhandler_pty_master *)fh)->need_nl)
{
gotone = s->read_ready = 1;
goto out;
}
break;
default:
if (!ignra && fh->get_readahead_valid ())
{
select_printf ("readahead");
gotone = s->read_ready = 1;
goto out;
}
}
if (fh->bg_check (SIGTTIN) <= bg_eof)
{
gotone = s->read_ready = 1;
goto out;
}
2000-02-18 03:38:33 +08:00
}
if (fh->get_device () == FH_PIPEW)
/* nothing */;
else if (!PeekNamedPipe (h, NULL, 0, NULL, (DWORD *) &n, NULL))
{
select_printf ("%s, PeekNamedPipe failed, %E", fh->get_name ());
n = -1;
}
else if (n && guard_mutex)
{
if (WaitForSingleObject (guard_mutex, 0) != WAIT_OBJECT_0)
{
select_printf ("%s, couldn't get mutex %p, %E", fh->get_name (),
guard_mutex);
n = 0;
}
/* 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. */
}
2000-02-18 03:38:33 +08:00
if (n < 0)
{
select_printf ("%s, n %d", fh->get_name (), n);
if (s->except_selected)
gotone += s->except_ready = TRUE;
if (s->read_selected)
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;
}
if (!gotone && s->fh->hit_eof ())
{
select_printf ("%s, saw EOF", fh->get_name ());
if (s->except_selected)
gotone = s->except_ready = TRUE;
if (s->read_selected)
gotone += s->read_ready = TRUE;
2000-04-12 05:22:53 +08:00
select_printf ("saw eof on '%s'", fh->get_name ());
2000-02-18 03:38:33 +08:00
}
out:
return gotone || s->write_ready;
}
static int
poll_pipe (select_record *me, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds)
{
2001-08-29 04:39:22 +08:00
return peek_pipe (me, 0) ?
set_bits (me, readfds, writefds, exceptfds) :
0;
2000-02-18 03:38:33 +08:00
}
2000-02-18 03:38:33 +08:00
static int start_thread_pipe (select_record *me, select_stuff *stuff);
struct pipeinf
{
HANDLE thread;
BOOL stop_thread_pipe;
select_record *start;
};
static DWORD WINAPI
thread_pipe (void *arg)
{
pipeinf *pi = (pipeinf *)arg;
BOOL gotone = FALSE;
for (;;)
{
select_record *s = pi->start;
while ((s = s->next))
if (s->startup == start_thread_pipe)
{
if (peek_pipe (s, 0))
gotone = TRUE;
if (pi->stop_thread_pipe)
{
select_printf ("stopping");
goto out;
}
}
/* Paranoid check */
if (pi->stop_thread_pipe)
{
select_printf ("stopping from outer loop");
break;
}
2000-02-18 03:38:33 +08:00
if (gotone)
break;
Sleep (10);
}
out:
return 0;
}
static int
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;
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");
if (!me->h)
return 0;
stuff->device_specific[FHDEVN(FH_PIPE)] = (void *)pi;
return 1;
}
static void
pipe_cleanup (select_record *, select_stuff *stuff)
2000-02-18 03:38:33 +08:00
{
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);
delete pi;
stuff->device_specific[FHDEVN(FH_PIPE)] = NULL;
}
}
select_record *
fhandler_pipe::select_read (select_record *s)
{
if (!s)
s = new select_record;
s->startup = start_thread_pipe;
s->poll = poll_pipe;
* dtable.cc (dtable::build_fhandler): Issue internal error on unknown device. * fhandler.cc (fhandler_base::close): Show both name and handle in debugging output. * fhandler.h (fhandler_base::get_guard): New virtual method. (fhandler_pipe::get_guard): New method. (fhandler_socket::ready_for_read): Delete declaration. (fhandler_pipe::ready_for_read): Ditto. (fhandler_serial::ready_for_read): Ditto. (fhandler_console::ready_for_read): Ditto. (fhandler_tty_common::ready_for_read): Ditto. (fhandler_windows::ready_for_read): Ditto. (struct select_record::peek): Declare new method. * select.cc (MAKEready): Delete. (peek_pipe): Use get_guard method to retrieve potential guard mutex handle. (fhandler_base::ready_for_read): Rewrite as generic ready-for-read handler. Should only be called for "slow" devices. (fhandler_socket::ready_for_read): Delete definition. (fhandler_pipe::ready_for_read): Ditto. (fhandler_serial::ready_for_read): Ditto. (fhandler_console::ready_for_read): Ditto. (fhandler_tty_common::ready_for_read): Ditto. (fhandler_windows::ready_for_read): Ditto. (fhandler_pipe::select_read): Fill in new peek record in select_record structure. (fhandler_console::select_read): Ditto. (fhandler_tty_common::select_read): Ditto. (fhandler_serial::select_read): Ditto. (fhandler_socket::select_read): Ditto. (fhandler_socket::select_read): Ditto. (fhandler_tty_slave::ready_for_read): Check for tty not open. Set errnos appropriately. * syscalls.cc (_read): Allow ready_for_read to set errno. * pinfo.cc (pinfo::init): Return spawn/NO_WAIT process as valid if it is initializing. * sigproc.cc (getsem): Adjust wait for process to initialize downward to avoid huge waits.
2001-11-02 05:15:53 +08:00
s->peek = peek_pipe;
2000-02-18 03:38:33 +08:00
s->verify = verify_ok;
s->read_selected = TRUE;
s->cleanup = pipe_cleanup;
return s;
}
select_record *
fhandler_pipe::select_write (select_record *s)
{
if (!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;
return s;
}
select_record *
fhandler_pipe::select_except (select_record *s)
{
if (!s)
s = new select_record;
s->startup = start_thread_pipe;
s->poll = poll_pipe;
s->verify = verify_ok;
s->cleanup = pipe_cleanup;
s->except_selected = TRUE;
return s;
}
static int
peek_console (select_record *me, int ignra)
{
extern const char * get_nonascii_key (INPUT_RECORD& input_rec, char *);
2000-02-18 03:38:33 +08:00
fhandler_console *fh = (fhandler_console *)me->fh;
if (!me->read_selected)
return me->write_ready;
if (!ignra && fh->get_readahead_valid ())
{
select_printf ("readahead");
return me->read_ready = 1;
}
if (me->read_ready)
{
select_printf ("already ready");
return 1;
}
2000-02-18 03:38:33 +08:00
INPUT_RECORD irec;
DWORD events_read;
HANDLE h;
char tmpbuf[17];
2000-02-18 03:38:33 +08:00
set_handle_or_return_if_not_open (h, me);
for (;;)
if (fh->bg_check (SIGTTIN) <= bg_eof)
2000-02-18 03:38:33 +08:00
return me->read_ready = 1;
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 (fh->mouse_aware ())
return me->read_ready = 1;
}
2000-02-18 03:38:33 +08:00
else if (irec.EventType == KEY_EVENT && irec.Event.KeyEvent.bKeyDown == TRUE &&
(irec.Event.KeyEvent.uChar.AsciiChar || get_nonascii_key (irec, tmpbuf)))
2000-02-18 03:38:33 +08:00
return me->read_ready = 1;
/* Read and discard the event */
ReadConsoleInput (h, &irec, 1, &events_read);
}
return me->write_ready;
}
static int
poll_console (select_record *me, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds)
{
return peek_console (me, 0) ?
set_bits (me, readfds, writefds, exceptfds) :
0;
}
select_record *
fhandler_console::select_read (select_record *s)
{
if (!s)
{
s = new select_record;
s->startup = no_startup;
s->poll = poll_console;
s->verify = poll_console;
set_cursor_maybe ();
2000-02-18 03:38:33 +08:00
}
* dtable.cc (dtable::build_fhandler): Issue internal error on unknown device. * fhandler.cc (fhandler_base::close): Show both name and handle in debugging output. * fhandler.h (fhandler_base::get_guard): New virtual method. (fhandler_pipe::get_guard): New method. (fhandler_socket::ready_for_read): Delete declaration. (fhandler_pipe::ready_for_read): Ditto. (fhandler_serial::ready_for_read): Ditto. (fhandler_console::ready_for_read): Ditto. (fhandler_tty_common::ready_for_read): Ditto. (fhandler_windows::ready_for_read): Ditto. (struct select_record::peek): Declare new method. * select.cc (MAKEready): Delete. (peek_pipe): Use get_guard method to retrieve potential guard mutex handle. (fhandler_base::ready_for_read): Rewrite as generic ready-for-read handler. Should only be called for "slow" devices. (fhandler_socket::ready_for_read): Delete definition. (fhandler_pipe::ready_for_read): Ditto. (fhandler_serial::ready_for_read): Ditto. (fhandler_console::ready_for_read): Ditto. (fhandler_tty_common::ready_for_read): Ditto. (fhandler_windows::ready_for_read): Ditto. (fhandler_pipe::select_read): Fill in new peek record in select_record structure. (fhandler_console::select_read): Ditto. (fhandler_tty_common::select_read): Ditto. (fhandler_serial::select_read): Ditto. (fhandler_socket::select_read): Ditto. (fhandler_socket::select_read): Ditto. (fhandler_tty_slave::ready_for_read): Check for tty not open. Set errnos appropriately. * syscalls.cc (_read): Allow ready_for_read to set errno. * pinfo.cc (pinfo::init): Return spawn/NO_WAIT process as valid if it is initializing. * sigproc.cc (getsem): Adjust wait for process to initialize downward to avoid huge waits.
2001-11-02 05:15:53 +08:00
s->peek = peek_console;
2000-02-18 03:38:33 +08:00
s->h = get_handle ();
s->read_selected = TRUE;
return s;
}
select_record *
fhandler_console::select_write (select_record *s)
{
if (!s)
{
s = new select_record;
s->startup = no_startup;
s->poll = poll_console;
s->verify = no_verify;
set_cursor_maybe ();
2000-02-18 03:38:33 +08:00
}
s->write_selected = TRUE;
s->write_ready = TRUE;
return s;
}
select_record *
fhandler_console::select_except (select_record *s)
{
if (!s)
{
s = new select_record;
s->startup = no_startup;
s->poll = poll_console;
s->verify = no_verify;
set_cursor_maybe ();
2000-02-18 03:38:33 +08:00
}
s->except_selected = TRUE;
return s;
}
select_record *
fhandler_tty_common::select_read (select_record *s)
{
return ((fhandler_pipe*)this)->fhandler_pipe::select_read (s);
}
select_record *
fhandler_tty_common::select_write (select_record *s)
{
return ((fhandler_pipe *)this)->fhandler_pipe::select_write (s);
}
select_record *
fhandler_tty_common::select_except (select_record *s)
{
return ((fhandler_pipe *)this)->fhandler_pipe::select_except (s);
}
static int
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;
return set_bits (me, readfds, writefds, exceptfds);
}
select_record *
fhandler_tty_slave::select_read (select_record *s)
{
if (!s)
s = new select_record;
s->h = input_available_event;
s->startup = no_startup;
s->poll = poll_pipe;
* dtable.cc (dtable::build_fhandler): Issue internal error on unknown device. * fhandler.cc (fhandler_base::close): Show both name and handle in debugging output. * fhandler.h (fhandler_base::get_guard): New virtual method. (fhandler_pipe::get_guard): New method. (fhandler_socket::ready_for_read): Delete declaration. (fhandler_pipe::ready_for_read): Ditto. (fhandler_serial::ready_for_read): Ditto. (fhandler_console::ready_for_read): Ditto. (fhandler_tty_common::ready_for_read): Ditto. (fhandler_windows::ready_for_read): Ditto. (struct select_record::peek): Declare new method. * select.cc (MAKEready): Delete. (peek_pipe): Use get_guard method to retrieve potential guard mutex handle. (fhandler_base::ready_for_read): Rewrite as generic ready-for-read handler. Should only be called for "slow" devices. (fhandler_socket::ready_for_read): Delete definition. (fhandler_pipe::ready_for_read): Ditto. (fhandler_serial::ready_for_read): Ditto. (fhandler_console::ready_for_read): Ditto. (fhandler_tty_common::ready_for_read): Ditto. (fhandler_windows::ready_for_read): Ditto. (fhandler_pipe::select_read): Fill in new peek record in select_record structure. (fhandler_console::select_read): Ditto. (fhandler_tty_common::select_read): Ditto. (fhandler_serial::select_read): Ditto. (fhandler_socket::select_read): Ditto. (fhandler_socket::select_read): Ditto. (fhandler_tty_slave::ready_for_read): Check for tty not open. Set errnos appropriately. * syscalls.cc (_read): Allow ready_for_read to set errno. * pinfo.cc (pinfo::init): Return spawn/NO_WAIT process as valid if it is initializing. * sigproc.cc (getsem): Adjust wait for process to initialize downward to avoid huge waits.
2001-11-02 05:15:53 +08:00
s->peek = peek_pipe;
s->verify = verify_tty_slave;
s->read_selected = TRUE;
s->cleanup = NULL;
return s;
}
int
fhandler_tty_slave::ready_for_read (int fd, DWORD howlong, int ignra)
{
HANDLE w4[2];
* dtable.cc (dtable::build_fhandler): Issue internal error on unknown device. * fhandler.cc (fhandler_base::close): Show both name and handle in debugging output. * fhandler.h (fhandler_base::get_guard): New virtual method. (fhandler_pipe::get_guard): New method. (fhandler_socket::ready_for_read): Delete declaration. (fhandler_pipe::ready_for_read): Ditto. (fhandler_serial::ready_for_read): Ditto. (fhandler_console::ready_for_read): Ditto. (fhandler_tty_common::ready_for_read): Ditto. (fhandler_windows::ready_for_read): Ditto. (struct select_record::peek): Declare new method. * select.cc (MAKEready): Delete. (peek_pipe): Use get_guard method to retrieve potential guard mutex handle. (fhandler_base::ready_for_read): Rewrite as generic ready-for-read handler. Should only be called for "slow" devices. (fhandler_socket::ready_for_read): Delete definition. (fhandler_pipe::ready_for_read): Ditto. (fhandler_serial::ready_for_read): Ditto. (fhandler_console::ready_for_read): Ditto. (fhandler_tty_common::ready_for_read): Ditto. (fhandler_windows::ready_for_read): Ditto. (fhandler_pipe::select_read): Fill in new peek record in select_record structure. (fhandler_console::select_read): Ditto. (fhandler_tty_common::select_read): Ditto. (fhandler_serial::select_read): Ditto. (fhandler_socket::select_read): Ditto. (fhandler_socket::select_read): Ditto. (fhandler_tty_slave::ready_for_read): Check for tty not open. Set errnos appropriately. * syscalls.cc (_read): Allow ready_for_read to set errno. * pinfo.cc (pinfo::init): Return spawn/NO_WAIT process as valid if it is initializing. * sigproc.cc (getsem): Adjust wait for process to initialize downward to avoid huge waits.
2001-11-02 05:15:53 +08:00
if (!cygheap->fdtab.not_open (fd))
{
set_errno (EBADF);
return 1;
}
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))
{
* dtable.cc (dtable::build_fhandler): Issue internal error on unknown device. * fhandler.cc (fhandler_base::close): Show both name and handle in debugging output. * fhandler.h (fhandler_base::get_guard): New virtual method. (fhandler_pipe::get_guard): New method. (fhandler_socket::ready_for_read): Delete declaration. (fhandler_pipe::ready_for_read): Ditto. (fhandler_serial::ready_for_read): Ditto. (fhandler_console::ready_for_read): Ditto. (fhandler_tty_common::ready_for_read): Ditto. (fhandler_windows::ready_for_read): Ditto. (struct select_record::peek): Declare new method. * select.cc (MAKEready): Delete. (peek_pipe): Use get_guard method to retrieve potential guard mutex handle. (fhandler_base::ready_for_read): Rewrite as generic ready-for-read handler. Should only be called for "slow" devices. (fhandler_socket::ready_for_read): Delete definition. (fhandler_pipe::ready_for_read): Ditto. (fhandler_serial::ready_for_read): Ditto. (fhandler_console::ready_for_read): Ditto. (fhandler_tty_common::ready_for_read): Ditto. (fhandler_windows::ready_for_read): Ditto. (fhandler_pipe::select_read): Fill in new peek record in select_record structure. (fhandler_console::select_read): Ditto. (fhandler_tty_common::select_read): Ditto. (fhandler_serial::select_read): Ditto. (fhandler_socket::select_read): Ditto. (fhandler_socket::select_read): Ditto. (fhandler_tty_slave::ready_for_read): Check for tty not open. Set errnos appropriately. * syscalls.cc (_read): Allow ready_for_read to set errno. * pinfo.cc (pinfo::init): Return spawn/NO_WAIT process as valid if it is initializing. * sigproc.cc (getsem): Adjust wait for process to initialize downward to avoid huge waits.
2001-11-02 05:15:53 +08:00
case WAIT_OBJECT_0:
set_errno (EINTR);
return 0;
case WAIT_OBJECT_0 + 1:
return 1;
case WAIT_FAILED:
2001-03-19 05:11:25 +08:00
select_printf ("wait failed %E");
* dtable.cc (dtable::build_fhandler): Issue internal error on unknown device. * fhandler.cc (fhandler_base::close): Show both name and handle in debugging output. * fhandler.h (fhandler_base::get_guard): New virtual method. (fhandler_pipe::get_guard): New method. (fhandler_socket::ready_for_read): Delete declaration. (fhandler_pipe::ready_for_read): Ditto. (fhandler_serial::ready_for_read): Ditto. (fhandler_console::ready_for_read): Ditto. (fhandler_tty_common::ready_for_read): Ditto. (fhandler_windows::ready_for_read): Ditto. (struct select_record::peek): Declare new method. * select.cc (MAKEready): Delete. (peek_pipe): Use get_guard method to retrieve potential guard mutex handle. (fhandler_base::ready_for_read): Rewrite as generic ready-for-read handler. Should only be called for "slow" devices. (fhandler_socket::ready_for_read): Delete definition. (fhandler_pipe::ready_for_read): Ditto. (fhandler_serial::ready_for_read): Ditto. (fhandler_console::ready_for_read): Ditto. (fhandler_tty_common::ready_for_read): Ditto. (fhandler_windows::ready_for_read): Ditto. (fhandler_pipe::select_read): Fill in new peek record in select_record structure. (fhandler_console::select_read): Ditto. (fhandler_tty_common::select_read): Ditto. (fhandler_serial::select_read): Ditto. (fhandler_socket::select_read): Ditto. (fhandler_socket::select_read): Ditto. (fhandler_tty_slave::ready_for_read): Check for tty not open. Set errnos appropriately. * syscalls.cc (_read): Allow ready_for_read to set errno. * pinfo.cc (pinfo::init): Return spawn/NO_WAIT process as valid if it is initializing. * sigproc.cc (getsem): Adjust wait for process to initialize downward to avoid huge waits.
2001-11-02 05:15:53 +08:00
set_errno (EINVAL); /* FIXME: correct errno? */
return 0;
default:
* dtable.cc (dtable::build_fhandler): Issue internal error on unknown device. * fhandler.cc (fhandler_base::close): Show both name and handle in debugging output. * fhandler.h (fhandler_base::get_guard): New virtual method. (fhandler_pipe::get_guard): New method. (fhandler_socket::ready_for_read): Delete declaration. (fhandler_pipe::ready_for_read): Ditto. (fhandler_serial::ready_for_read): Ditto. (fhandler_console::ready_for_read): Ditto. (fhandler_tty_common::ready_for_read): Ditto. (fhandler_windows::ready_for_read): Ditto. (struct select_record::peek): Declare new method. * select.cc (MAKEready): Delete. (peek_pipe): Use get_guard method to retrieve potential guard mutex handle. (fhandler_base::ready_for_read): Rewrite as generic ready-for-read handler. Should only be called for "slow" devices. (fhandler_socket::ready_for_read): Delete definition. (fhandler_pipe::ready_for_read): Ditto. (fhandler_serial::ready_for_read): Ditto. (fhandler_console::ready_for_read): Ditto. (fhandler_tty_common::ready_for_read): Ditto. (fhandler_windows::ready_for_read): Ditto. (fhandler_pipe::select_read): Fill in new peek record in select_record structure. (fhandler_console::select_read): Ditto. (fhandler_tty_common::select_read): Ditto. (fhandler_serial::select_read): Ditto. (fhandler_socket::select_read): Ditto. (fhandler_socket::select_read): Ditto. (fhandler_tty_slave::ready_for_read): Check for tty not open. Set errnos appropriately. * syscalls.cc (_read): Allow ready_for_read to set errno. * pinfo.cc (pinfo::init): Return spawn/NO_WAIT process as valid if it is initializing. * sigproc.cc (getsem): Adjust wait for process to initialize downward to avoid huge waits.
2001-11-02 05:15:53 +08:00
if (!howlong)
set_errno (EAGAIN);
return 0;
}
}
2000-02-18 03:38:33 +08:00
select_record *
fhandler_dev_null::select_read (select_record *s)
{
if (!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;
2000-02-18 03:38:33 +08:00
return s;
}
select_record *
fhandler_dev_null::select_write (select_record *s)
{
if (!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;
2000-02-18 03:38:33 +08:00
return s;
}
select_record *
fhandler_dev_null::select_except (select_record *s)
{
if (!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;
return s;
}
static int start_thread_serial (select_record *me, select_stuff *stuff);
struct serialinf
{
HANDLE thread;
BOOL stop_thread_serial;
select_record *start;
};
static int
peek_serial (select_record *s, int)
{
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;
select_printf ("fh->overlapped_armed %d", fh->overlapped_armed);
HANDLE h;
set_handle_or_return_if_not_open (h, s);
int ready = 0;
if (s->read_selected && s->read_ready || (s->write_selected && s->write_ready))
{
select_printf ("already ready");
ready = 1;
goto out;
}
2000-02-18 03:38:33 +08:00
(void) SetCommMask (h, EV_RXCHAR);
if (!fh->overlapped_armed)
{
DWORD ev;
COMSTAT st;
ResetEvent (fh->io_status.hEvent);
if (!ClearCommError (h, &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;
else if (GetLastError () == ERROR_IO_PENDING)
fh->overlapped_armed = 1;
else
{
debug_printf ("WaitCommEvent");
goto err;
}
}
HANDLE w4[2];
DWORD to;
w4[0] = fh->io_status.hEvent;
w4[1] = signal_arrived;
to = 10;
switch (WaitForMultipleObjects (2, w4, FALSE, to))
{
case WAIT_OBJECT_0:
if (!ClearCommError (h, &ev, &st))
* Makefile.in: Add cygheap.o. * child_info.h: Add specific exec class. * cygheap.h: New file. Contains declarations for cygwin heap. * cygheap.cc: New file. Implements cygwin heap functions. * dcrt0.cc (quoted): Simplify due to new method for passing arguments between cygwin programs. (alloc_stack_hard_way): Attempt to handle overlapped stack. (dll_crt0_1): Move child_info processing here. Accomodate new method for passing arguments between cygwin programs. Initialize cygwin heap. Establish __argc and __argv variables. (_dll_crt0): Move most of child_info processing to dll_crt0_1. (cygwin_dll_init): Remove duplication. * dtable.cc (dtable::extend): Allocate dtable using cygwin heap. (dtable::build_fhandler): Ditto for fhandler type being constructed. (dtable::dup_worker): Free new fhandler from cygwin heap on error. (dtable::select_*): Don't assume that this == fdtab. (dtable::linearize_fd_array): Delete. (dtable::delinearize_fd_array): Delete. (dtable::fixup_after_exec): New file. (dtable::vfork_child_dup): Use cygwin heap. (dtable::vfork_parent_restore): Ditto. * dtable.h: Remove obsolete methods. Add new method. * environ.cc (posify): Eliminate already_posix parameter and logic. (envsize): New function. (_addenv): Use envsize. (environ_init): Accept an argument pointing to an existing environment list. If supplied, allocate space for this in the the program's heap. * fhandler.cc (fhandler_base::operator =): Move here from fhandler.h. Use cygwin heap to allocate filenames. (fhandler_base::set_name): Allocate/free names from cygwin heap. (fhandler_base::linearize): Delete. (fhandler_base::de_linearize): Delete. (fhandler_base::operator delete): Free from cygwin heap. (fhandler_base::~fhandler_base): Ditto. * fhandler.h: Accomodate elimination of *linearize and other changes above. * fhandler_console.cc (fhandler_console::fixup_after_exec): Rename from de_linearize. * heap.h: New file. * fhandler_tty.cc (fhandler_tty_slave::fhandler_tty_slave): Use cygwin heap for name. fhandler_tty::fixup_after_exec): Rename from de_linearize. * fork.cc (fork): Call cygheap_fixup_in_child. * heap.cc: Use declarations in heap.h. * malloc.cc: Sprinkle assertions throughout to catch attempts to free/realloc something from the cygwin heap. * path.cc: Throughout, eliminate use of per-thread cache for cwd. Use cwd_* functions rather than cwd_* variables to access cwd_win32 and cwd_posix. (cwd_win32): New function. (cwd_posix): New function. (cwd_hash): New function. (cwd_fixup_after_exec): New function. * path.h: Accomodate path.cc changes. * pinfo.cc (pinfo_init): Accept a pointer to an environment table. Pass this to environ_init. Eliminate old 'title' tests. * pinfo.h: Accomodate above change in argument. * spawn.cc (struct av): New method for building argv list. (av::unshift): New method. (spawn_guts): Allocate everything that the child process needs in the cygwin heap and pass a pointer to this to the child. Build argv list using new method. Eliminate delinearize stuff. * thread.h: Eliminate _cwd_win32 and _cwd_posix buffers. * winsup.h: Eliminate obsolete functions. Add envsize() declaration.
2000-09-03 12:16:35 +08:00
{
debug_printf ("ClearCommError");
goto err;
}
2000-02-18 03:38:33 +08:00
else if (!st.cbInQue)
Sleep (to);
else
{
return s->read_ready = 1;
select_printf ("got something");
}
PurgeComm (h, PURGE_TXABORT | PURGE_RXABORT);
break;
case WAIT_OBJECT_0 + 1:
PurgeComm (h, PURGE_TXABORT | PURGE_RXABORT);
select_printf ("interrupt");
set_sig_errno (EINTR);
ready = -1;
break;
case WAIT_TIMEOUT:
PurgeComm (h, PURGE_TXABORT | PURGE_RXABORT);
break;
default:
PurgeComm (h, PURGE_TXABORT | PURGE_RXABORT);
debug_printf ("WaitForMultipleObjects");
goto err;
}
out:
2000-02-18 03:38:33 +08:00
return ready;
err:
if (GetLastError () == ERROR_OPERATION_ABORTED)
{
select_printf ("operation aborted");
return ready;
}
__seterrno ();
s->saw_error = TRUE;
select_printf ("error %E");
return -1;
}
static DWORD WINAPI
thread_serial (void *arg)
{
serialinf *si = (serialinf *)arg;
BOOL gotone= FALSE;
for (;;)
{
select_record *s = si->start;
while ((s = s->next))
if (s->startup == start_thread_serial)
{
if (peek_serial (s, 0))
gotone = TRUE;
}
if (si->stop_thread_serial)
{
select_printf ("stopping");
break;
}
if (gotone)
break;
}
select_printf ("exiting");
return 0;
}
static int
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;
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;
stuff->device_specific[FHDEVN(FH_SERIAL)] = (void *)si;
return 1;
}
static void
serial_cleanup (select_record *, select_stuff *stuff)
2000-02-18 03:38:33 +08:00
{
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);
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;
}
select_record *
fhandler_serial::select_read (select_record *s)
{
if (!s)
{
s = new select_record;
s->startup = start_thread_serial;
s->poll = poll_serial;
s->verify = verify_ok;
s->cleanup = serial_cleanup;
}
* dtable.cc (dtable::build_fhandler): Issue internal error on unknown device. * fhandler.cc (fhandler_base::close): Show both name and handle in debugging output. * fhandler.h (fhandler_base::get_guard): New virtual method. (fhandler_pipe::get_guard): New method. (fhandler_socket::ready_for_read): Delete declaration. (fhandler_pipe::ready_for_read): Ditto. (fhandler_serial::ready_for_read): Ditto. (fhandler_console::ready_for_read): Ditto. (fhandler_tty_common::ready_for_read): Ditto. (fhandler_windows::ready_for_read): Ditto. (struct select_record::peek): Declare new method. * select.cc (MAKEready): Delete. (peek_pipe): Use get_guard method to retrieve potential guard mutex handle. (fhandler_base::ready_for_read): Rewrite as generic ready-for-read handler. Should only be called for "slow" devices. (fhandler_socket::ready_for_read): Delete definition. (fhandler_pipe::ready_for_read): Ditto. (fhandler_serial::ready_for_read): Ditto. (fhandler_console::ready_for_read): Ditto. (fhandler_tty_common::ready_for_read): Ditto. (fhandler_windows::ready_for_read): Ditto. (fhandler_pipe::select_read): Fill in new peek record in select_record structure. (fhandler_console::select_read): Ditto. (fhandler_tty_common::select_read): Ditto. (fhandler_serial::select_read): Ditto. (fhandler_socket::select_read): Ditto. (fhandler_socket::select_read): Ditto. (fhandler_tty_slave::ready_for_read): Check for tty not open. Set errnos appropriately. * syscalls.cc (_read): Allow ready_for_read to set errno. * pinfo.cc (pinfo::init): Return spawn/NO_WAIT process as valid if it is initializing. * sigproc.cc (getsem): Adjust wait for process to initialize downward to avoid huge waits.
2001-11-02 05:15:53 +08:00
s->peek = peek_serial;
2000-02-18 03:38:33 +08:00
s->read_selected = TRUE;
return s;
}
select_record *
fhandler_serial::select_write (select_record *s)
{
if (!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;
return s;
}
select_record *
fhandler_serial::select_except (select_record *s)
{
if (!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
return s;
}
int
* dtable.cc (dtable::build_fhandler): Issue internal error on unknown device. * fhandler.cc (fhandler_base::close): Show both name and handle in debugging output. * fhandler.h (fhandler_base::get_guard): New virtual method. (fhandler_pipe::get_guard): New method. (fhandler_socket::ready_for_read): Delete declaration. (fhandler_pipe::ready_for_read): Ditto. (fhandler_serial::ready_for_read): Ditto. (fhandler_console::ready_for_read): Ditto. (fhandler_tty_common::ready_for_read): Ditto. (fhandler_windows::ready_for_read): Ditto. (struct select_record::peek): Declare new method. * select.cc (MAKEready): Delete. (peek_pipe): Use get_guard method to retrieve potential guard mutex handle. (fhandler_base::ready_for_read): Rewrite as generic ready-for-read handler. Should only be called for "slow" devices. (fhandler_socket::ready_for_read): Delete definition. (fhandler_pipe::ready_for_read): Ditto. (fhandler_serial::ready_for_read): Ditto. (fhandler_console::ready_for_read): Ditto. (fhandler_tty_common::ready_for_read): Ditto. (fhandler_windows::ready_for_read): Ditto. (fhandler_pipe::select_read): Fill in new peek record in select_record structure. (fhandler_console::select_read): Ditto. (fhandler_tty_common::select_read): Ditto. (fhandler_serial::select_read): Ditto. (fhandler_socket::select_read): Ditto. (fhandler_socket::select_read): Ditto. (fhandler_tty_slave::ready_for_read): Check for tty not open. Set errnos appropriately. * syscalls.cc (_read): Allow ready_for_read to set errno. * pinfo.cc (pinfo::init): Return spawn/NO_WAIT process as valid if it is initializing. * sigproc.cc (getsem): Adjust wait for process to initialize downward to avoid huge waits.
2001-11-02 05:15:53 +08:00
fhandler_base::ready_for_read (int fd, DWORD howlong, int ignra)
2000-02-18 03:38:33 +08:00
{
* dtable.cc (dtable::build_fhandler): Issue internal error on unknown device. * fhandler.cc (fhandler_base::close): Show both name and handle in debugging output. * fhandler.h (fhandler_base::get_guard): New virtual method. (fhandler_pipe::get_guard): New method. (fhandler_socket::ready_for_read): Delete declaration. (fhandler_pipe::ready_for_read): Ditto. (fhandler_serial::ready_for_read): Ditto. (fhandler_console::ready_for_read): Ditto. (fhandler_tty_common::ready_for_read): Ditto. (fhandler_windows::ready_for_read): Ditto. (struct select_record::peek): Declare new method. * select.cc (MAKEready): Delete. (peek_pipe): Use get_guard method to retrieve potential guard mutex handle. (fhandler_base::ready_for_read): Rewrite as generic ready-for-read handler. Should only be called for "slow" devices. (fhandler_socket::ready_for_read): Delete definition. (fhandler_pipe::ready_for_read): Ditto. (fhandler_serial::ready_for_read): Ditto. (fhandler_console::ready_for_read): Ditto. (fhandler_tty_common::ready_for_read): Ditto. (fhandler_windows::ready_for_read): Ditto. (fhandler_pipe::select_read): Fill in new peek record in select_record structure. (fhandler_console::select_read): Ditto. (fhandler_tty_common::select_read): Ditto. (fhandler_serial::select_read): Ditto. (fhandler_socket::select_read): Ditto. (fhandler_socket::select_read): Ditto. (fhandler_tty_slave::ready_for_read): Check for tty not open. Set errnos appropriately. * syscalls.cc (_read): Allow ready_for_read to set errno. * pinfo.cc (pinfo::init): Return spawn/NO_WAIT process as valid if it is initializing. * sigproc.cc (getsem): Adjust wait for process to initialize downward to avoid huge waits.
2001-11-02 05:15:53 +08:00
int avail = 0;
select_record me (this);
me.read_ready = false;
* dtable.cc (dtable::build_fhandler): Issue internal error on unknown device. * fhandler.cc (fhandler_base::close): Show both name and handle in debugging output. * fhandler.h (fhandler_base::get_guard): New virtual method. (fhandler_pipe::get_guard): New method. (fhandler_socket::ready_for_read): Delete declaration. (fhandler_pipe::ready_for_read): Ditto. (fhandler_serial::ready_for_read): Ditto. (fhandler_console::ready_for_read): Ditto. (fhandler_tty_common::ready_for_read): Ditto. (fhandler_windows::ready_for_read): Ditto. (struct select_record::peek): Declare new method. * select.cc (MAKEready): Delete. (peek_pipe): Use get_guard method to retrieve potential guard mutex handle. (fhandler_base::ready_for_read): Rewrite as generic ready-for-read handler. Should only be called for "slow" devices. (fhandler_socket::ready_for_read): Delete definition. (fhandler_pipe::ready_for_read): Ditto. (fhandler_serial::ready_for_read): Ditto. (fhandler_console::ready_for_read): Ditto. (fhandler_tty_common::ready_for_read): Ditto. (fhandler_windows::ready_for_read): Ditto. (fhandler_pipe::select_read): Fill in new peek record in select_record structure. (fhandler_console::select_read): Ditto. (fhandler_tty_common::select_read): Ditto. (fhandler_serial::select_read): Ditto. (fhandler_socket::select_read): Ditto. (fhandler_socket::select_read): Ditto. (fhandler_tty_slave::ready_for_read): Check for tty not open. Set errnos appropriately. * syscalls.cc (_read): Allow ready_for_read to set errno. * pinfo.cc (pinfo::init): Return spawn/NO_WAIT process as valid if it is initializing. * sigproc.cc (getsem): Adjust wait for process to initialize downward to avoid huge waits.
2001-11-02 05:15:53 +08:00
me.fd = fd;
while (!avail)
{
(void) select_read (&me);
avail = me.read_ready ?: me.peek (&me, ignra);
if (fd >= 0 && cygheap->fdtab.not_open (fd))
{
set_errno (EBADF);
avail = 0;
break;
}
if (howlong != INFINITE)
{
if (!avail)
set_errno (EAGAIN);
break;
}
if (WaitForSingleObject (signal_arrived, avail ? 0 : 10) == WAIT_OBJECT_0)
{
set_errno (EINTR);
avail = 0;
break;
}
}
if (get_guard () && !avail && me.read_ready)
ReleaseMutex (get_guard ());
* dtable.cc (dtable::build_fhandler): Issue internal error on unknown device. * fhandler.cc (fhandler_base::close): Show both name and handle in debugging output. * fhandler.h (fhandler_base::get_guard): New virtual method. (fhandler_pipe::get_guard): New method. (fhandler_socket::ready_for_read): Delete declaration. (fhandler_pipe::ready_for_read): Ditto. (fhandler_serial::ready_for_read): Ditto. (fhandler_console::ready_for_read): Ditto. (fhandler_tty_common::ready_for_read): Ditto. (fhandler_windows::ready_for_read): Ditto. (struct select_record::peek): Declare new method. * select.cc (MAKEready): Delete. (peek_pipe): Use get_guard method to retrieve potential guard mutex handle. (fhandler_base::ready_for_read): Rewrite as generic ready-for-read handler. Should only be called for "slow" devices. (fhandler_socket::ready_for_read): Delete definition. (fhandler_pipe::ready_for_read): Ditto. (fhandler_serial::ready_for_read): Ditto. (fhandler_console::ready_for_read): Ditto. (fhandler_tty_common::ready_for_read): Ditto. (fhandler_windows::ready_for_read): Ditto. (fhandler_pipe::select_read): Fill in new peek record in select_record structure. (fhandler_console::select_read): Ditto. (fhandler_tty_common::select_read): Ditto. (fhandler_serial::select_read): Ditto. (fhandler_socket::select_read): Ditto. (fhandler_socket::select_read): Ditto. (fhandler_tty_slave::ready_for_read): Check for tty not open. Set errnos appropriately. * syscalls.cc (_read): Allow ready_for_read to set errno. * pinfo.cc (pinfo::init): Return spawn/NO_WAIT process as valid if it is initializing. * sigproc.cc (getsem): Adjust wait for process to initialize downward to avoid huge waits.
2001-11-02 05:15:53 +08:00
select_printf ("read_ready %d, avail %d", me.read_ready, avail);
return avail;
2000-02-18 03:38:33 +08:00
}
select_record *
fhandler_base::select_read (select_record *s)
{
if (!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;
return s;
}
select_record *
fhandler_base::select_write (select_record *s)
{
if (!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;
return s;
}
select_record *
fhandler_base::select_except (select_record *s)
{
if (!s)
{
s = new select_record;
s->startup = no_startup;
s->poll = set_bits;
s->verify = verify_ok;
}
s->h = NULL;
s->write_selected = TRUE;
return s;
}
struct socketinf
{
HANDLE thread;
winsock_fd_set readfds, writefds, exceptfds;
SOCKET exitsock;
struct sockaddr_in sin;
select_record *start;
};
static int
peek_socket (select_record *me, int)
{
winsock_fd_set ws_readfds, ws_writefds, ws_exceptfds;
struct timeval tv = {0, 0};
2000-02-18 03:38:33 +08:00
WINSOCK_FD_ZERO (&ws_readfds);
WINSOCK_FD_ZERO (&ws_writefds);
WINSOCK_FD_ZERO (&ws_exceptfds);
HANDLE h;
set_handle_or_return_if_not_open (h, me);
select_printf ("considering handle %p", h);
if (me->read_selected)
{
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)
{
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)
{
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)
{
select_printf ("error %d", WSAGetLastError ());
set_winsock_errno ();
2000-02-18 03:38:33 +08:00
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_ready))
me->except_ready = TRUE;
return me->read_ready || me->write_ready || me->except_ready;
2000-02-18 03:38:33 +08:00
}
static int
poll_socket (select_record *me, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds)
{
2001-08-29 04:39:22 +08:00
return peek_socket (me, 0) ?
set_bits (me, readfds, writefds, exceptfds) :
0;
2000-02-18 03:38:33 +08:00
}
static int start_thread_socket (select_record *, select_stuff *);
static DWORD WINAPI
thread_socket (void *arg)
{
socketinf *si = (socketinf *)arg;
select_printf ("stuff_start %p", &si->start);
int r = WINSOCK_SELECT (0, &si->readfds, &si->writefds, &si->exceptfds, NULL);
select_printf ("Win32 select returned %d", r);
if (r == -1)
select_printf ("error %d", WSAGetLastError ());
select_record *s = si->start;
while ((s = s->next))
if (s->startup == start_thread_socket)
{
HANDLE h = s->fh->get_handle ();
select_printf ("s %p, testing fd %d (%s)", s, s->fd, s->fh->get_name ());
if (WINSOCK_FD_ISSET (h, &si->readfds))
{
select_printf ("read_ready");
s->read_ready = TRUE;
}
if (WINSOCK_FD_ISSET (h, &si->writefds))
{
select_printf ("write_ready");
s->write_ready = TRUE;
}
if (WINSOCK_FD_ISSET (h, &si->exceptfds))
{
select_printf ("except_ready");
s->except_ready = TRUE;
}
}
if (WINSOCK_FD_ISSET (si->exitsock, &si->readfds))
select_printf ("saw exitsock read");
return 0;
}
extern "C" unsigned long htonl (unsigned long);
static int
start_thread_socket (select_record *me, select_stuff *stuff)
{
socketinf *si;
if ((si = (socketinf *)stuff->device_specific[FHDEVN(FH_SOCKET)]))
{
me->h = si->thread;
return 1;
}
si = new socketinf;
WINSOCK_FD_ZERO (&si->readfds);
WINSOCK_FD_ZERO (&si->writefds);
WINSOCK_FD_ZERO (&si->exceptfds);
select_record *s = &stuff->start;
while ((s = s->next))
if (s->startup == start_thread_socket)
{
HANDLE h = s->fh->get_handle ();
select_printf ("Handle %p", h);
if (s->read_selected)
{
WINSOCK_FD_SET (h, &si->readfds);
select_printf ("Added to readfds");
}
if (s->write_selected)
{
WINSOCK_FD_SET (h, &si->writefds);
select_printf ("Added to writefds");
}
if (s->except_selected)
{
WINSOCK_FD_SET (h, &si->exceptfds);
select_printf ("Added to exceptfds");
}
}
if ((si->exitsock = socket (PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
{
set_winsock_errno ();
select_printf ("cannot create socket, %E");
return -1;
}
/* Allow rapid reuse of the port. */
int tmp = 1;
(void) setsockopt (si->exitsock, SOL_SOCKET, SO_REUSEADDR, (char *) &tmp, sizeof (tmp));
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);
if (bind (si->exitsock, (struct sockaddr *) &si->sin, sizeof (si->sin)) < 0)
{
select_printf ("cannot bind socket, %E");
goto err;
}
if (getsockname (si->exitsock, (struct sockaddr *) &si->sin, &sin_len) < 0)
{
select_printf ("getsockname error");
goto err;
}
if (listen (si->exitsock, 1))
{
select_printf ("listen failed, %E");
goto err;
}
select_printf ("exitsock %p", si->exitsock);
WINSOCK_FD_SET ((HANDLE) si->exitsock, &si->readfds);
WINSOCK_FD_SET ((HANDLE) si->exitsock, &si->exceptfds);
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;
err:
set_winsock_errno ();
closesocket (si->exitsock);
return -1;
}
void
socket_cleanup (select_record *, select_stuff *stuff)
2000-02-18 03:38:33 +08:00
{
socketinf *si = (socketinf *)stuff->device_specific[FHDEVN(FH_SOCKET)];
select_printf ("si %p si->thread %p", si, si ? si->thread : NULL);
if (si && si->thread)
{
select_printf ("connection to si->exitsock %p", si->exitsock);
SOCKET s = socket (AF_INET, SOCK_STREAM, 0);
/* 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));
2000-02-18 03:38:33 +08:00
/* Connecting to si->exitsock will cause any executing select to wake
up. When this happens then the exitsock condition will cause the
thread to terminate. */
if (connect (s, (struct sockaddr *) &si->sin, sizeof (si->sin)) < 0)
{
set_winsock_errno ();
select_printf ("connect failed");
/* FIXME: now what? */
}
shutdown (s, SD_BOTH);
2000-02-18 03:38:33 +08:00
closesocket (s);
/* Wait for thread to go away */
WaitForSingleObject (si->thread, INFINITE);
shutdown (si->exitsock, SD_BOTH);
2000-02-18 03:38:33 +08:00
closesocket (si->exitsock);
CloseHandle (si->thread);
stuff->device_specific[FHDEVN(FH_SOCKET)] = NULL;
delete si;
}
select_printf ("returning");
}
select_record *
fhandler_socket::select_read (select_record *s)
{
if (!s)
{
s = new select_record;
s->startup = start_thread_socket;
s->poll = poll_socket;
s->verify = verify_true;
s->cleanup = socket_cleanup;
}
* dtable.cc (dtable::build_fhandler): Issue internal error on unknown device. * fhandler.cc (fhandler_base::close): Show both name and handle in debugging output. * fhandler.h (fhandler_base::get_guard): New virtual method. (fhandler_pipe::get_guard): New method. (fhandler_socket::ready_for_read): Delete declaration. (fhandler_pipe::ready_for_read): Ditto. (fhandler_serial::ready_for_read): Ditto. (fhandler_console::ready_for_read): Ditto. (fhandler_tty_common::ready_for_read): Ditto. (fhandler_windows::ready_for_read): Ditto. (struct select_record::peek): Declare new method. * select.cc (MAKEready): Delete. (peek_pipe): Use get_guard method to retrieve potential guard mutex handle. (fhandler_base::ready_for_read): Rewrite as generic ready-for-read handler. Should only be called for "slow" devices. (fhandler_socket::ready_for_read): Delete definition. (fhandler_pipe::ready_for_read): Ditto. (fhandler_serial::ready_for_read): Ditto. (fhandler_console::ready_for_read): Ditto. (fhandler_tty_common::ready_for_read): Ditto. (fhandler_windows::ready_for_read): Ditto. (fhandler_pipe::select_read): Fill in new peek record in select_record structure. (fhandler_console::select_read): Ditto. (fhandler_tty_common::select_read): Ditto. (fhandler_serial::select_read): Ditto. (fhandler_socket::select_read): Ditto. (fhandler_socket::select_read): Ditto. (fhandler_tty_slave::ready_for_read): Check for tty not open. Set errnos appropriately. * syscalls.cc (_read): Allow ready_for_read to set errno. * pinfo.cc (pinfo::init): Return spawn/NO_WAIT process as valid if it is initializing. * sigproc.cc (getsem): Adjust wait for process to initialize downward to avoid huge waits.
2001-11-02 05:15:53 +08:00
s->peek = peek_socket;
s->read_ready = saw_shutdown_read ();
2000-02-18 03:38:33 +08:00
s->read_selected = TRUE;
return s;
}
select_record *
fhandler_socket::select_write (select_record *s)
{
if (!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 ();
2000-02-18 03:38:33 +08:00
s->write_selected = TRUE;
return s;
}
select_record *
fhandler_socket::select_except (select_record *s)
{
if (!s)
{
s = new select_record;
s->startup = start_thread_socket;
s->poll = poll_socket;
s->verify = verify_true;
s->cleanup = socket_cleanup;
}
/* FIXME: Is this right? Should these be used as criteria for except? */
s->except_ready = saw_shutdown_write () || saw_shutdown_read ();
2000-02-18 03:38:33 +08:00
s->except_selected = TRUE;
return s;
}
static int
peek_windows (select_record *me, int)
{
MSG m;
HANDLE h;
set_handle_or_return_if_not_open (h, me);
if (me->read_selected && me->read_ready)
return 1;
2000-02-18 03:38:33 +08:00
if (PeekMessage (&m, (HWND) h, 0, 0, PM_NOREMOVE))
{
me->read_ready = TRUE;
select_printf ("window %d(%p) ready", me->fd, me->fh->get_handle ());
return 1;
}
select_printf ("window %d(%p) not ready", me->fd, me->fh->get_handle ());
return me->write_ready;
}
static int
poll_windows (select_record *me, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds)
{
return peek_windows (me, 0) ?
set_bits (me, readfds, writefds, exceptfds) :
0;
}
select_record *
fhandler_windows::select_read (select_record *s)
{
if (!s)
{
s = new select_record;
s->startup = no_startup;
s->poll = poll_windows;
s->verify = poll_windows;
}
* dtable.cc (dtable::build_fhandler): Issue internal error on unknown device. * fhandler.cc (fhandler_base::close): Show both name and handle in debugging output. * fhandler.h (fhandler_base::get_guard): New virtual method. (fhandler_pipe::get_guard): New method. (fhandler_socket::ready_for_read): Delete declaration. (fhandler_pipe::ready_for_read): Ditto. (fhandler_serial::ready_for_read): Ditto. (fhandler_console::ready_for_read): Ditto. (fhandler_tty_common::ready_for_read): Ditto. (fhandler_windows::ready_for_read): Ditto. (struct select_record::peek): Declare new method. * select.cc (MAKEready): Delete. (peek_pipe): Use get_guard method to retrieve potential guard mutex handle. (fhandler_base::ready_for_read): Rewrite as generic ready-for-read handler. Should only be called for "slow" devices. (fhandler_socket::ready_for_read): Delete definition. (fhandler_pipe::ready_for_read): Ditto. (fhandler_serial::ready_for_read): Ditto. (fhandler_console::ready_for_read): Ditto. (fhandler_tty_common::ready_for_read): Ditto. (fhandler_windows::ready_for_read): Ditto. (fhandler_pipe::select_read): Fill in new peek record in select_record structure. (fhandler_console::select_read): Ditto. (fhandler_tty_common::select_read): Ditto. (fhandler_serial::select_read): Ditto. (fhandler_socket::select_read): Ditto. (fhandler_socket::select_read): Ditto. (fhandler_tty_slave::ready_for_read): Check for tty not open. Set errnos appropriately. * syscalls.cc (_read): Allow ready_for_read to set errno. * pinfo.cc (pinfo::init): Return spawn/NO_WAIT process as valid if it is initializing. * sigproc.cc (getsem): Adjust wait for process to initialize downward to avoid huge waits.
2001-11-02 05:15:53 +08:00
s->peek = peek_windows;
2000-02-18 03:38:33 +08:00
s->h = get_handle ();
s->read_selected = TRUE;
s->h = get_handle ();
s->windows_handle = TRUE;
return s;
}
select_record *
fhandler_windows::select_write (select_record *s)
{
if (!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->windows_handle = TRUE;
return s;
}
select_record *
fhandler_windows::select_except (select_record *s)
{
if (!s)
{
s = new select_record;
s->startup = no_startup;
s->poll = set_bits;
s->verify = verify_ok;
}
s->h = get_handle ();
s->except_selected = TRUE;
s->except_ready = TRUE;
s->windows_handle = TRUE;
return s;
}