* select.h: New file split from fhandler.h.

(select_record::select_record): Define do-nothing constructor for "new" to
avoid gratuitous zeroing.
(select_info): New base class.
(select_pipe_info): New class with methods for dealing with pipes.
(select_socket_info): New class with methods for dealing with sockets.
(select_serial_info): Dummy class for serial.
(select_mailslot_info): Dummy class for mailslots.
(select_stuff): Define device_specific_* as actual classes rather than void *.
* dtable.h (dtable::select_read): Accommodate return value change to 'bool' and
argument change to "select_stuff".
(dtable::select_write): Ditto.
(dtable::select_except): Ditto.
* dtable.cc (dtable::select_read): Accommodate return value change to 'bool'
and argument change to "select_stuff".
(dtable::select_write): Ditto.
(dtable::select_except): Ditto.
* fhandler.h: Excise select-related classes.
(fhandler_*::select_read): Change argument to select_stuff.
(fhandler_*::select_write): Ditto.
(fhandler_*::select_except): Ditto.
* select.cc (UNIX_FD_ZERO): Use memset rather than bzero.
(select_stuff::test_and_set): Change return type to bool.  Allocate
select_record on entry and let fhandler_*::select_* operate on the start.next
field of select_stuff.
(pipeinf): Delete.
(select_pipe_info::select_pipe_info): New constructor.  Allocates event for
controlling pipe waits.
(select_pipe_info::~select_pipe_info): New destructor.  Destroy event.  Stop
thread.
(select_pipe_info::add_watch_handle): New function.
(thread_pipe): Wait for the hEvent part of any overlapped pipes before peeking.
(start_thread_pipe): Don't allocate device_specific_pipe stuff here.  Assume
that it has been allocated earlier.
(pipe_cleanup): Rely on select_pipe_info destructor to clean up pipe
paraphenalia.
(fhandler_*::select_*): Derive select_record from new select_stuff argument.
(fhandler_pipe::select_*): Ditto.  Allocate pipe-specific field if not already
allocated.
(serialinf): Delete.
(thread_serial): serialinf -> select_serial_info.
(fhandler_base::ready_for_read): Rewrite to accommodate change in argument to
fhandler_*::select_*.
(socketinf): Delete.
(thread_socket): socketinf -> select_socket_info.
(mailslotinf): Delete.
(thread_mailslot): mailslotinf -> select_mailslot_info.
This commit is contained in:
Christopher Faylor 2009-06-30 21:18:44 +00:00
parent 840bb39798
commit b4fa816474
13 changed files with 457 additions and 330 deletions

View File

@ -1,3 +1,56 @@
2009-06-30 Christopher Faylor <me+cygwin@cgf.cx>
* select.h: New file split from fhandler.h.
(select_record::select_record): Define do-nothing constructor for "new"
to avoid gratuitous zeroing.
(select_info): New base class.
(select_pipe_info): New class with methods for dealing with pipes.
(select_socket_info): New class with methods for dealing with sockets.
(select_serial_info): Dummy class for serial.
(select_mailslot_info): Dummy class for mailslots.
(select_stuff): Define device_specific_* as actual classes rather than
void *.
* dtable.h (dtable::select_read): Accommodate return value change to
'bool' and argument change to "select_stuff".
(dtable::select_write): Ditto.
(dtable::select_except): Ditto.
* dtable.cc (dtable::select_read): Accommodate return value change to
'bool' and argument change to "select_stuff".
(dtable::select_write): Ditto.
(dtable::select_except): Ditto.
* fhandler.h: Excise select-related classes.
(fhandler_*::select_read): Change argument to select_stuff.
(fhandler_*::select_write): Ditto.
(fhandler_*::select_except): Ditto.
* select.cc (UNIX_FD_ZERO): Use memset rather than bzero.
(select_stuff::test_and_set): Change return type to bool. Allocate
select_record on entry and let fhandler_*::select_* operate on the
start.next field of select_stuff.
(pipeinf): Delete.
(select_pipe_info::select_pipe_info): New constructor. Allocates event
for controlling pipe waits.
(select_pipe_info::~select_pipe_info): New destructor. Destroy event.
Stop thread.
(select_pipe_info::add_watch_handle): New function.
(thread_pipe): Wait for the hEvent part of any overlapped pipes before
peeking.
(start_thread_pipe): Don't allocate device_specific_pipe stuff here.
Assume that it has been allocated earlier.
(pipe_cleanup): Rely on select_pipe_info destructor to clean up pipe
paraphenalia.
(fhandler_*::select_*): Derive select_record from new select_stuff
argument.
(fhandler_pipe::select_*): Ditto. Allocate pipe-specific field if not
already allocated.
(serialinf): Delete.
(thread_serial): serialinf -> select_serial_info.
(fhandler_base::ready_for_read): Rewrite to accommodate change in
argument to fhandler_*::select_*.
(socketinf): Delete.
(thread_socket): socketinf -> select_socket_info.
(mailslotinf): Delete.
(thread_mailslot): mailslotinf -> select_mailslot_info.
2009-06-30 Christopher Faylor <me+cygwin@cgf.cx>
* fhandler.cc (fhandler_base::has_ongoing_io): Accept an argument

View File

@ -109,7 +109,7 @@ class cygheap_user
/* Extendend user information.
The information is derived from the internal_getlogin call
when on a NT system. */
char *pname; /* user's name */
char *pname; /* user's name */
char *plogsrv; /* Logon server, may be FQDN */
char *pdomain; /* Logon domain of the user */
char *homedrive; /* User's home drive */

View File

@ -25,6 +25,7 @@ details. */
#include "perprocess.h"
#include "path.h"
#include "fhandler.h"
#include "select.h"
#include "dtable.h"
#include "cygheap.h"
#include "tls_pbuf.h"
@ -359,7 +360,7 @@ dtable::init_std_file_from_handle (int fd, HANDLE handle)
access |= GENERIC_WRITE; /* Should be rdwr for stderr but not sure that's
possible for some versions of handles */
/* FIXME: Workaround Windows 7 64 bit issue. If the parent process of
the process tree closes the original handles to the console window,
the process tree closes the original handles to the console window,
strange problems occur when starting child processes later on if
stdio redirection is used. How to reproduce:
@ -378,7 +379,7 @@ dtable::init_std_file_from_handle (int fd, HANDLE handle)
Remove the `exec 2>' or remove the cat call and the script will work.
Start bash interactively, then start the script manually, and the
script will work.
This needs further investigation but the workaround not to close
the handles will have a marginal hit of three extra handles per
process at most. */
@ -654,26 +655,26 @@ done:
return res;
}
select_record *
dtable::select_read (int fd, select_record *s)
bool
dtable::select_read (int fd, select_stuff *ss)
{
if (not_open (fd))
{
set_errno (EBADF);
return NULL;
return false;
}
fhandler_base *fh = fds[fd];
s = fh->select_read (s);
select_record *s = fh->select_read (ss);
s->fd = fd;
if (!s->fh)
s->fh = fh;
s->thread_errno = 0;
debug_printf ("%s fd %d", fh->get_name (), fd);
return s;
return true;
}
select_record *
dtable::select_write (int fd, select_record *s)
bool
dtable::select_write (int fd, select_stuff *ss)
{
if (not_open (fd))
{
@ -681,16 +682,16 @@ dtable::select_write (int fd, select_record *s)
return NULL;
}
fhandler_base *fh = fds[fd];
s = fh->select_write (s);
select_record *s = fh->select_write (ss);
s->fd = fd;
s->fh = fh;
s->thread_errno = 0;
debug_printf ("%s fd %d", fh->get_name (), fd);
return s;
debug_printf ("%s fd %d", fh->get_name ());
return true;
}
select_record *
dtable::select_except (int fd, select_record *s)
bool
dtable::select_except (int fd, select_stuff *ss)
{
if (not_open (fd))
{
@ -698,12 +699,12 @@ dtable::select_except (int fd, select_record *s)
return NULL;
}
fhandler_base *fh = fds[fd];
s = fh->select_except (s);
select_record *s = fh->select_except (ss);
s->fd = fd;
s->fh = fh;
s->thread_errno = 0;
debug_printf ("%s fd %d", fh->get_name (), fd);
return s;
return true;
}
void

View File

@ -57,9 +57,9 @@ public:
int dup2 (int oldfd, int newfd);
void fixup_after_exec ();
inline fhandler_base *&operator [](int fd) const { return fds[fd]; }
select_record *select_read (int fd, select_record *s);
select_record *select_write (int fd, select_record *s);
select_record *select_except (int fd, select_record *s);
bool select_read (int fd, select_stuff *);
bool select_write (int fd, select_stuff *);
bool select_except (int fd, select_stuff *);
operator fhandler_base **() {return fds;}
void stdio_init ();
void get_debugger_info ();

View File

@ -37,6 +37,7 @@ extern const char proc[];
extern const int proc_len;
class select_record;
class select_stuff;
class fhandler_disk_file;
class inode_t;
typedef struct __DIR DIR;
@ -354,9 +355,9 @@ class fhandler_base
virtual HANDLE& get_io_handle () { return io_handle; }
virtual HANDLE& get_output_handle () { return io_handle; }
virtual bool hit_eof () {return false;}
virtual select_record *select_read (select_record *s);
virtual select_record *select_write (select_record *s);
virtual select_record *select_except (select_record *s);
virtual select_record *select_read (select_stuff *);
virtual select_record *select_write (select_stuff *);
virtual select_record *select_except (select_stuff *);
virtual int ready_for_read (int fd, DWORD howlong);
virtual const char *get_native_name ()
{
@ -394,7 +395,7 @@ class fhandler_mailslot : public fhandler_base
int open (int flags, mode_t mode = 0);
int write (const void *ptr, size_t len);
int ioctl (unsigned int cmd, void *);
select_record *select_read (select_record *s);
select_record *select_read (select_stuff *);
};
struct wsa_event
@ -507,9 +508,9 @@ class fhandler_socket: public fhandler_base
void fixup_after_fork (HANDLE);
char *get_proc_fd_name (char *buf);
select_record *select_read (select_record *s);
select_record *select_write (select_record *s);
select_record *select_except (select_record *s);
select_record *select_read (select_stuff *);
select_record *select_write (select_stuff *);
select_record *select_except (select_stuff *);
int ready_for_read (int, DWORD) { return true; }
void set_addr_family (int af) {addr_family = af;}
int get_addr_family () {return addr_family;}
@ -543,9 +544,9 @@ public:
void set_popen_pid (pid_t pid) {popen_pid = pid;}
pid_t get_popen_pid () const {return popen_pid;}
_off64_t lseek (_off64_t offset, int whence);
select_record *select_read (select_record *s);
select_record *select_write (select_record *s);
select_record *select_except (select_record *s);
select_record *select_read (select_stuff *);
select_record *select_write (select_stuff *);
select_record *select_except (select_stuff *);
char *get_proc_fd_name (char *buf);
void raw_read (void *ptr, size_t& len);
int raw_write (const void *, size_t);
@ -584,9 +585,9 @@ public:
int __stdcall fstatvfs (struct statvfs *buf) __attribute__ ((regparm (2)));
OVERLAPPED *get_overlapped () {return &io_status;}
OVERLAPPED *get_overlapped_buffer () {return &io_status;}
select_record *select_read (select_record *s);
select_record *select_write (select_record *s);
select_record *select_except (select_record *s);
select_record *select_read (select_stuff *);
select_record *select_write (select_stuff *);
select_record *select_except (select_stuff *);
};
class fhandler_dev_raw: public fhandler_base
@ -784,9 +785,9 @@ class fhandler_serial: public fhandler_base
permission checking on pgrps. */
virtual int tcgetpgrp () { return pgrp_; }
virtual int tcsetpgrp (const pid_t pid) { pgrp_ = pid; return 0; }
select_record *select_read (select_record *s);
select_record *select_write (select_record *s);
select_record *select_except (select_record *s);
select_record *select_read (select_stuff *);
select_record *select_write (select_stuff *);
select_record *select_except (select_stuff *);
bool is_slow () {return true;}
};
@ -964,9 +965,9 @@ class fhandler_console: public fhandler_termios
void init (HANDLE, DWORD, mode_t);
bool mouse_aware () {return dev_state->use_mouse;}
select_record *select_read (select_record *s);
select_record *select_write (select_record *s);
select_record *select_except (select_record *s);
select_record *select_read (select_stuff *);
select_record *select_write (select_stuff *);
select_record *select_except (select_stuff *);
void fixup_after_fork_exec (bool);
void fixup_after_exec () {fixup_after_fork_exec (true);}
void fixup_after_fork (HANDLE) {fixup_after_fork_exec (false);}
@ -1006,9 +1007,9 @@ class fhandler_tty_common: public fhandler_termios
int close ();
_off64_t lseek (_off64_t, int);
void set_close_on_exec (bool val);
select_record *select_read (select_record *s);
select_record *select_write (select_record *s);
select_record *select_except (select_record *s);
select_record *select_read (select_stuff *);
select_record *select_write (select_stuff *);
select_record *select_except (select_stuff *);
bool is_slow () {return true;}
};
@ -1033,7 +1034,7 @@ class fhandler_tty_slave: public fhandler_tty_common
void fixup_after_fork (HANDLE parent);
void fixup_after_exec ();
select_record *select_read (select_record *s);
select_record *select_read (select_stuff *);
int cygserver_attach_tty (HANDLE*, HANDLE*);
int get_unit ();
virtual char const *ttyname () { return pc.dev.name; }
@ -1090,9 +1091,9 @@ class fhandler_dev_null: public fhandler_base
public:
fhandler_dev_null ();
select_record *select_read (select_record *s);
select_record *select_write (select_record *s);
select_record *select_except (select_record *s);
select_record *select_read (select_stuff *);
select_record *select_write (select_stuff *);
select_record *select_except (select_stuff *);
};
class fhandler_dev_zero: public fhandler_base
@ -1194,9 +1195,9 @@ class fhandler_windows: public fhandler_base
void set_close_on_exec (bool val);
void fixup_after_fork (HANDLE parent);
select_record *select_read (select_record *s);
select_record *select_write (select_record *s);
select_record *select_except (select_record *s);
select_record *select_read (select_stuff *);
select_record *select_write (select_stuff *);
select_record *select_except (select_stuff *);
bool is_slow () {return true;}
};
@ -1384,55 +1385,4 @@ typedef union
char __virtual[sizeof (fhandler_virtual)];
char __windows[sizeof (fhandler_windows)];
} fhandler_union;
struct select_record
{
int fd;
HANDLE h;
fhandler_base *fh;
int thread_errno;
bool windows_handle;
bool read_ready, write_ready, except_ready;
bool read_selected, write_selected, except_selected;
bool except_on_write;
int (*startup) (select_record *me, class select_stuff *stuff);
int (*peek) (select_record *, bool);
int (*verify) (select_record *me, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds);
void (*cleanup) (select_record *me, class select_stuff *stuff);
struct select_record *next;
void set_select_errno () {__seterrno (); thread_errno = errno;}
int saw_error () {return thread_errno;}
select_record (fhandler_base *in_fh = NULL) : fd (0), h (NULL),
fh (in_fh), thread_errno (0), windows_handle (false),
read_ready (false), write_ready (false), except_ready (false),
read_selected (false), write_selected (false),
except_selected (false), except_on_write (false),
startup (NULL), peek (NULL), verify (NULL), cleanup (NULL),
next (NULL) {}
};
class select_stuff
{
public:
~select_stuff ();
bool always_ready, windows_used;
select_record start;
void *device_specific_pipe;
void *device_specific_socket;
void *device_specific_serial;
void *device_specific_mailslot;
int test_and_set (int i, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds);
int poll (fd_set *readfds, fd_set *writefds, fd_set *exceptfds);
int wait (fd_set *readfds, fd_set *writefds, fd_set *exceptfds, DWORD ms);
void cleanup ();
select_stuff (): always_ready (0), windows_used (0), start (0),
device_specific_pipe (0),
device_specific_socket (0),
device_specific_serial (0),
device_specific_mailslot (0) {}
};
#endif /* _FHANDLER_H_ */

View File

@ -209,7 +209,7 @@ fhandler_dev_clipboard::read (void *ptr, size_t& len)
if (format == cygnativeformat)
{
unsigned char *buf;
if (!(buf = (unsigned char *) GlobalLock (hglb)))
{
CloseClipboard ();

View File

@ -286,7 +286,7 @@ class inode_t
void wait () { ++i_wait; }
void unwait () { if (i_wait > 0) --i_wait; }
bool waiting () { return i_wait > 0; }
bool waiting () { return i_wait > 0; }
lockf_t *get_all_locks_list ();

View File

@ -16,8 +16,8 @@ class fs_info
{
struct status_flags
{
ULONG flags; /* Volume flags */
ULONG samba_version; /* Samba version if available */
ULONG flags; /* Volume flags */
ULONG samba_version; /* Samba version if available */
ULONG name_len; /* MaximumComponentNameLength */
unsigned is_remote_drive : 1;
unsigned has_buggy_open : 1;

View File

@ -27,6 +27,7 @@ details. */
#include "security.h"
#include "path.h"
#include "fhandler.h"
#include "select.h"
#include "dtable.h"
#include "cygheap.h"
#include "pinfo.h"
@ -68,7 +69,7 @@ typedef long fd_mask;
#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)))
memset ((caddr_t) (p), 0, sizeof_fd_set ((n)))
#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));
@ -205,19 +206,27 @@ select_stuff::~select_stuff ()
}
/* Add a record to the select chain */
int
bool
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)
return 0; /* error */
if (UNIX_FD_ISSET (i, writefds) && (s = cygheap->fdtab.select_write (i, s)) == NULL)
return 0; /* error */
if (UNIX_FD_ISSET (i, exceptfds) && (s = cygheap->fdtab.select_except (i, s)) == NULL)
return 0; /* error */
if (s == NULL)
return 1; /* nothing to do */
if (!UNIX_FD_ISSET (i, readfds) && !UNIX_FD_ISSET (i, writefds)
&& ! UNIX_FD_ISSET (i, exceptfds))
return true;
select_record *s = new select_record;
if (!s)
return false;
s->next = start.next;
start.next = s;
if (UNIX_FD_ISSET (i, readfds) && !cygheap->fdtab.select_read (i, this))
goto err;
if (UNIX_FD_ISSET (i, writefds) && !cygheap->fdtab.select_write (i, this))
goto err;
if (UNIX_FD_ISSET (i, exceptfds) && !cygheap->fdtab.select_except (i, this))
goto err; /* error */
if (s->read_ready || s->write_ready || s->except_ready)
always_ready = true;
@ -225,9 +234,12 @@ select_stuff::test_and_set (int i, fd_set *readfds, fd_set *writefds,
if (s->windows_handle)
windows_used = true;
s->next = start.next;
start.next = s;
return 1;
return true;
err:
start.next = s->next;
delete s;
return false;
}
/* The heart of select. Waits for an fd to do something interesting. */
@ -566,36 +578,61 @@ out:
static int start_thread_pipe (select_record *me, select_stuff *stuff);
struct pipeinf
{
cygthread *thread;
bool stop_thread_pipe;
select_record *start;
};
select_pipe_info::select_pipe_info ()
{
n = 1;
w4[0] = CreateEvent (&sec_none_nih, true, false, NULL);
}
select_pipe_info::~select_pipe_info ()
{
if (thread)
{
SetEvent (w4[0]);
stop_thread = true;
thread->detach ();
}
ForceCloseHandle (w4[0]);
}
void
select_pipe_info::add_watch_handle (fhandler_pipe *fh)
{
if (fh->get_overlapped () && fh->get_overlapped ()->hEvent)
w4[n++] = fh->get_overlapped ()->hEvent;
}
static DWORD WINAPI
thread_pipe (void *arg)
{
pipeinf *pi = (pipeinf *) arg;
select_pipe_info *pi = (select_pipe_info *) arg;
bool gotone = false;
DWORD sleep_time = 0;
for (;;)
{
select_record *s = pi->start;
if (pi->n > 1)
switch (WaitForMultipleObjects (pi->n, pi->w4, false, INFINITE))
{
case WAIT_OBJECT_0:
goto out;
default:
break;
}
while ((s = s->next))
if (s->startup == start_thread_pipe)
{
if (peek_pipe (s, true))
gotone = true;
if (pi->stop_thread_pipe)
if (pi->stop_thread)
{
select_printf ("stopping");
goto out;
}
}
/* Paranoid check */
if (pi->stop_thread_pipe)
if (pi->stop_thread)
{
select_printf ("stopping from outer loop");
break;
@ -613,31 +650,27 @@ out:
static int
start_thread_pipe (select_record *me, select_stuff *stuff)
{
if (stuff->device_specific_pipe)
select_pipe_info *pi = stuff->device_specific_pipe;
if (pi->start)
me->h = *((select_pipe_info *) stuff->device_specific_pipe)->thread;
else
{
me->h = *((pipeinf *) stuff->device_specific_pipe)->thread;
return 1;
pi->start = &stuff->start;
pi->stop_thread = false;
pi->thread = new cygthread (thread_pipe, 0, pi, "select_pipe");
me->h = *pi->thread;
if (!me->h)
return 0;
}
pipeinf *pi = new pipeinf;
pi->start = &stuff->start;
pi->stop_thread_pipe = false;
pi->thread = new cygthread (thread_pipe, 0, pi, "select_pipe");
me->h = *pi->thread;
if (!me->h)
return 0;
stuff->device_specific_pipe = (void *) pi;
return 1;
}
static void
pipe_cleanup (select_record *, select_stuff *stuff)
{
pipeinf *pi = (pipeinf *) stuff->device_specific_pipe;
if (pi && pi->thread)
if (stuff->device_specific_pipe)
{
pi->stop_thread_pipe = true;
pi->thread->detach ();
delete pi;
delete stuff->device_specific_pipe;
stuff->device_specific_pipe = NULL;
}
}
@ -654,10 +687,14 @@ fhandler_pipe::ready_for_read (int fd, DWORD howlong)
}
select_record *
fhandler_pipe::select_read (select_record *s)
fhandler_pipe::select_read (select_stuff *ss)
{
if (!s)
s = new select_record;
if (!ss->device_specific_pipe
&& (ss->device_specific_pipe = new select_pipe_info) == NULL)
return NULL;
ss->device_specific_pipe->add_watch_handle (this);
select_record *s = ss->start.next;
s->startup = start_thread_pipe;
s->peek = peek_pipe;
s->verify = verify_ok;
@ -668,10 +705,13 @@ fhandler_pipe::select_read (select_record *s)
}
select_record *
fhandler_pipe::select_write (select_record *s)
fhandler_pipe::select_write (select_stuff *ss)
{
if (!s)
s = new select_record;
if (!ss->device_specific_pipe
&& (ss->device_specific_pipe = new select_pipe_info) == NULL)
return NULL;
ss->device_specific_pipe->add_watch_handle (this);
select_record *s = ss->start.next;
s->startup = start_thread_pipe;
s->peek = peek_pipe;
s->verify = verify_ok;
@ -682,10 +722,13 @@ fhandler_pipe::select_write (select_record *s)
}
select_record *
fhandler_pipe::select_except (select_record *s)
fhandler_pipe::select_except (select_stuff *ss)
{
if (!s)
s = new select_record;
if (!ss->device_specific_pipe
&& (ss->device_specific_pipe = new select_pipe_info) == NULL)
return NULL;
ss->device_specific_pipe->add_watch_handle (this);
select_record *s = ss->start.next;
s->startup = start_thread_pipe;
s->peek = peek_pipe;
s->verify = verify_ok;
@ -696,10 +739,9 @@ fhandler_pipe::select_except (select_record *s)
}
select_record *
fhandler_fifo::select_read (select_record *s)
fhandler_fifo::select_read (select_stuff *ss)
{
if (!s)
s = new select_record;
select_record *s = ss->start.next;
s->startup = start_thread_pipe;
s->peek = peek_pipe;
s->verify = verify_ok;
@ -710,10 +752,9 @@ fhandler_fifo::select_read (select_record *s)
}
select_record *
fhandler_fifo::select_write (select_record *s)
fhandler_fifo::select_write (select_stuff *ss)
{
if (!s)
s = new select_record;
select_record *s = ss->start.next;
s->startup = start_thread_pipe;
s->peek = peek_pipe;
s->verify = verify_ok;
@ -724,10 +765,9 @@ fhandler_fifo::select_write (select_record *s)
}
select_record *
fhandler_fifo::select_except (select_record *s)
fhandler_fifo::select_except (select_stuff *ss)
{
if (!s)
s = new select_record;
select_record *s = ss->start.next;
s->startup = start_thread_pipe;
s->peek = peek_pipe;
s->verify = verify_ok;
@ -804,11 +844,11 @@ verify_console (select_record *me, fd_set *rfds, fd_set *wfds,
select_record *
fhandler_console::select_read (select_record *s)
fhandler_console::select_read (select_stuff *ss)
{
if (!s)
select_record *s = ss->start.next;
if (!s->startup)
{
s = new select_record;
s->startup = no_startup;
s->verify = verify_console;
set_cursor_maybe ();
@ -822,11 +862,11 @@ fhandler_console::select_read (select_record *s)
}
select_record *
fhandler_console::select_write (select_record *s)
fhandler_console::select_write (select_stuff *ss)
{
if (!s)
select_record *s = ss->start.next;
if (!s->startup)
{
s = new select_record;
s->startup = no_startup;
s->verify = no_verify;
set_cursor_maybe ();
@ -839,11 +879,11 @@ fhandler_console::select_write (select_record *s)
}
select_record *
fhandler_console::select_except (select_record *s)
fhandler_console::select_except (select_stuff *ss)
{
if (!s)
select_record *s = ss->start.next;
if (!s->startup)
{
s = new select_record;
s->startup = no_startup;
s->verify = no_verify;
set_cursor_maybe ();
@ -856,21 +896,21 @@ fhandler_console::select_except (select_record *s)
}
select_record *
fhandler_tty_common::select_read (select_record *s)
fhandler_tty_common::select_read (select_stuff *ss)
{
return ((fhandler_pipe *) this)->fhandler_pipe::select_read (s);
return ((fhandler_pipe *) this)->fhandler_pipe::select_read (ss);
}
select_record *
fhandler_tty_common::select_write (select_record *s)
fhandler_tty_common::select_write (select_stuff *ss)
{
return ((fhandler_pipe *) this)->fhandler_pipe::select_write (s);
return ((fhandler_pipe *) this)->fhandler_pipe::select_write (ss);
}
select_record *
fhandler_tty_common::select_except (select_record *s)
fhandler_tty_common::select_except (select_stuff *ss)
{
return ((fhandler_pipe *) this)->fhandler_pipe::select_except (s);
return ((fhandler_pipe *) this)->fhandler_pipe::select_except (ss);
}
static int
@ -883,10 +923,9 @@ verify_tty_slave (select_record *me, fd_set *readfds, fd_set *writefds,
}
select_record *
fhandler_tty_slave::select_read (select_record *s)
fhandler_tty_slave::select_read (select_stuff *ss)
{
if (!s)
s = new select_record;
select_record *s = ss->start.next;
s->h = input_available_event;
s->startup = no_startup;
s->peek = peek_pipe;
@ -898,11 +937,11 @@ fhandler_tty_slave::select_read (select_record *s)
}
select_record *
fhandler_dev_null::select_read (select_record *s)
fhandler_dev_null::select_read (select_stuff *ss)
{
if (!s)
select_record *s = ss->start.next;
if (!s->startup)
{
s = new select_record;
s->startup = no_startup;
s->verify = no_verify;
}
@ -913,11 +952,11 @@ fhandler_dev_null::select_read (select_record *s)
}
select_record *
fhandler_dev_null::select_write (select_record *s)
fhandler_dev_null::select_write (select_stuff *ss)
{
if (!s)
select_record *s = ss->start.next;
if (!s->startup)
{
s = new select_record;
s->startup = no_startup;
s->verify = no_verify;
}
@ -928,11 +967,11 @@ fhandler_dev_null::select_write (select_record *s)
}
select_record *
fhandler_dev_null::select_except (select_record *s)
fhandler_dev_null::select_except (select_stuff *ss)
{
if (!s)
select_record *s = ss->start.next;
if (!s->startup)
{
s = new select_record;
s->startup = no_startup;
s->verify = no_verify;
}
@ -944,13 +983,6 @@ fhandler_dev_null::select_except (select_record *s)
static int start_thread_serial (select_record *me, select_stuff *stuff);
struct serialinf
{
cygthread *thread;
bool stop_thread_serial;
select_record *start;
};
static int
peek_serial (select_record *s, bool)
{
@ -1057,7 +1089,7 @@ err:
static DWORD WINAPI
thread_serial (void *arg)
{
serialinf *si = (serialinf *) arg;
select_serial_info *si = (select_serial_info *) arg;
bool gotone = false;
for (;;)
@ -1069,7 +1101,7 @@ thread_serial (void *arg)
if (peek_serial (s, true))
gotone = true;
}
if (si->stop_thread_serial)
if (si->stop_thread)
{
select_printf ("stopping");
break;
@ -1086,26 +1118,26 @@ static int
start_thread_serial (select_record *me, select_stuff *stuff)
{
if (stuff->device_specific_serial)
me->h = *((select_serial_info *) stuff->device_specific_serial)->thread;
else
{
me->h = *((serialinf *) stuff->device_specific_serial)->thread;
return 1;
select_serial_info *si = new select_serial_info;
si->start = &stuff->start;
si->stop_thread = false;
si->thread = new cygthread (thread_serial, 0, si, "select_serial");
me->h = *si->thread;
stuff->device_specific_serial = si;
}
serialinf *si = new serialinf;
si->start = &stuff->start;
si->stop_thread_serial = false;
si->thread = new cygthread (thread_serial, 0, si, "select_serial");
me->h = *si->thread;
stuff->device_specific_serial = (void *) si;
return 1;
}
static void
serial_cleanup (select_record *, select_stuff *stuff)
{
serialinf *si = (serialinf *) stuff->device_specific_serial;
select_serial_info *si = (select_serial_info *) stuff->device_specific_serial;
if (si && si->thread)
{
si->stop_thread_serial = true;
si->stop_thread = true;
si->thread->detach ();
delete si;
stuff->device_specific_serial = NULL;
@ -1113,11 +1145,11 @@ serial_cleanup (select_record *, select_stuff *stuff)
}
select_record *
fhandler_serial::select_read (select_record *s)
fhandler_serial::select_read (select_stuff *ss)
{
if (!s)
select_record *s = ss->start.next;
if (!s->startup)
{
s = new select_record;
s->startup = start_thread_serial;
s->verify = verify_ok;
s->cleanup = serial_cleanup;
@ -1129,11 +1161,11 @@ fhandler_serial::select_read (select_record *s)
}
select_record *
fhandler_serial::select_write (select_record *s)
fhandler_serial::select_write (select_stuff *ss)
{
if (!s)
select_record *s = ss->start.next;
if (!s->startup)
{
s = new select_record;
s->startup = no_startup;
s->verify = verify_ok;
}
@ -1145,11 +1177,11 @@ fhandler_serial::select_write (select_record *s)
}
select_record *
fhandler_serial::select_except (select_record *s)
fhandler_serial::select_except (select_stuff *ss)
{
if (!s)
select_record *s = ss->start.next;
if (!s->startup)
{
s = new select_record;
s->startup = no_startup;
s->verify = verify_ok;
}
@ -1164,46 +1196,57 @@ int
fhandler_base::ready_for_read (int fd, DWORD howlong)
{
bool avail = false;
select_record me (this);
me.fd = fd;
while (!avail)
select_stuff sel;
fd_set *thisfd = allocfd_set (fd + 1);
fd_set *dummy_writefds = allocfd_set (fd + 1);
fd_set *dummy_exceptfds = allocfd_set (fd + 1);
UNIX_FD_SET(fd, thisfd);
if (!sel.test_and_set (fd, thisfd, dummy_writefds, dummy_exceptfds))
select_printf ("aborting due to test_and_set error");
else
{
select_read (&me);
avail = me.read_ready ?: me.peek (&me, false);
if (fd >= 0 && cygheap->fdtab.not_open (fd))
select_record *me = sel.start.next;
while (!avail)
{
set_sig_errno (EBADF);
avail = false;
break;
}
avail = me->read_ready ?: me->peek (me, false);
if (howlong != INFINITE)
{
if (!avail)
set_sig_errno (EAGAIN);
break;
}
if (fd >= 0 && cygheap->fdtab.not_open (fd))
{
set_sig_errno (EBADF);
avail = false;
break;
}
if (WaitForSingleObject (signal_arrived, avail ? 0 : 10) == WAIT_OBJECT_0)
{
debug_printf ("interrupted");
set_sig_errno (EINTR);
avail = false;
break;
if (howlong != INFINITE)
{
if (!avail)
set_sig_errno (EAGAIN);
break;
}
if (WaitForSingleObject (signal_arrived, avail ? 0 : 10) == WAIT_OBJECT_0)
{
debug_printf ("interrupted");
set_sig_errno (EINTR);
avail = false;
break;
}
}
}
select_printf ("read_ready %d, avail %d", me.read_ready, avail);
select_printf ("read_ready %d, avail %d", sel.start.next->read_ready, avail);
sel.cleanup ();
return avail;
}
select_record *
fhandler_base::select_read (select_record *s)
fhandler_base::select_read (select_stuff *ss)
{
if (!s)
select_record *s = ss->start.next;
if (!s->startup)
{
s = new select_record;
s->startup = no_startup;
s->verify = verify_ok;
}
@ -1214,11 +1257,11 @@ fhandler_base::select_read (select_record *s)
}
select_record *
fhandler_base::select_write (select_record *s)
fhandler_base::select_write (select_stuff *ss)
{
if (!s)
select_record *s = ss->start.next;
if (!s->startup)
{
s = new select_record;
s->startup = no_startup;
s->verify = verify_ok;
}
@ -1229,11 +1272,11 @@ fhandler_base::select_write (select_record *s)
}
select_record *
fhandler_base::select_except (select_record *s)
fhandler_base::select_except (select_stuff *ss)
{
if (!s)
select_record *s = ss->start.next;
if (!s->startup)
{
s = new select_record;
s->startup = no_startup;
s->verify = verify_ok;
}
@ -1268,20 +1311,10 @@ peek_socket (select_record *me, bool)
static int start_thread_socket (select_record *, select_stuff *);
struct socketinf
{
cygthread *thread;
int max_w4;
int num_w4;
LONG *ser_num;
HANDLE *w4;
select_record *start;
};
static DWORD WINAPI
thread_socket (void *arg)
{
socketinf *si = (socketinf *) arg;
select_socket_info *si = (select_socket_info *) arg;
DWORD timeout = 64 / (si->max_w4 / MAXIMUM_WAIT_OBJECTS);
bool event = false;
@ -1317,15 +1350,15 @@ out:
static int
start_thread_socket (select_record *me, select_stuff *stuff)
{
socketinf *si;
select_socket_info *si;
if ((si = (socketinf *) stuff->device_specific_socket))
if ((si = (select_socket_info *) stuff->device_specific_socket))
{
me->h = *si->thread;
return 1;
}
si = new socketinf;
si = new select_socket_info;
si->ser_num = (LONG *) malloc (MAXIMUM_WAIT_OBJECTS * sizeof (LONG));
si->w4 = (HANDLE *) malloc (MAXIMUM_WAIT_OBJECTS * sizeof (HANDLE));
if (!si->ser_num || !si->w4)
@ -1370,7 +1403,7 @@ start_thread_socket (select_record *me, select_stuff *stuff)
continue_outer_loop:
;
}
stuff->device_specific_socket = (void *) si;
stuff->device_specific_socket = si;
si->start = &stuff->start;
select_printf ("stuff_start %p", &stuff->start);
si->thread = new cygthread (thread_socket, 0, si, "select_socket");
@ -1381,7 +1414,7 @@ start_thread_socket (select_record *me, select_stuff *stuff)
void
socket_cleanup (select_record *, select_stuff *stuff)
{
socketinf *si = (socketinf *) stuff->device_specific_socket;
select_socket_info *si = (select_socket_info *) stuff->device_specific_socket;
select_printf ("si %p si->thread %p", si, si ? si->thread : NULL);
if (si && si->thread)
{
@ -1400,11 +1433,11 @@ socket_cleanup (select_record *, select_stuff *stuff)
}
select_record *
fhandler_socket::select_read (select_record *s)
fhandler_socket::select_read (select_stuff *ss)
{
if (!s)
select_record *s = ss->start.next;
if (!s->startup)
{
s = new select_record;
s->startup = start_thread_socket;
s->verify = verify_true;
s->cleanup = socket_cleanup;
@ -1416,11 +1449,11 @@ fhandler_socket::select_read (select_record *s)
}
select_record *
fhandler_socket::select_write (select_record *s)
fhandler_socket::select_write (select_stuff *ss)
{
if (!s)
select_record *s = ss->start.next;
if (!s->startup)
{
s = new select_record;
s->startup = start_thread_socket;
s->verify = verify_true;
s->cleanup = socket_cleanup;
@ -1437,11 +1470,11 @@ fhandler_socket::select_write (select_record *s)
}
select_record *
fhandler_socket::select_except (select_record *s)
fhandler_socket::select_except (select_stuff *ss)
{
if (!s)
select_record *s = ss->start.next;
if (!s->startup)
{
s = new select_record;
s->startup = start_thread_socket;
s->verify = verify_true;
s->cleanup = socket_cleanup;
@ -1482,11 +1515,11 @@ verify_windows (select_record *me, fd_set *rfds, fd_set *wfds,
}
select_record *
fhandler_windows::select_read (select_record *s)
fhandler_windows::select_read (select_stuff *ss)
{
if (!s)
select_record *s = ss->start.next;
if (!s->startup)
{
s = new select_record;
s->startup = no_startup;
}
s->verify = verify_windows;
@ -1499,11 +1532,11 @@ fhandler_windows::select_read (select_record *s)
}
select_record *
fhandler_windows::select_write (select_record *s)
fhandler_windows::select_write (select_stuff *ss)
{
if (!s)
select_record *s = ss->start.next;
if (!s->startup)
{
s = new select_record;
s->startup = no_startup;
s->verify = verify_ok;
}
@ -1516,11 +1549,11 @@ fhandler_windows::select_write (select_record *s)
}
select_record *
fhandler_windows::select_except (select_record *s)
fhandler_windows::select_except (select_stuff *ss)
{
if (!s)
select_record *s = ss->start.next;
if (!s->startup)
{
s = new select_record;
s->startup = no_startup;
s->verify = verify_ok;
}
@ -1565,17 +1598,10 @@ verify_mailslot (select_record *me, fd_set *rfds, fd_set *wfds,
static int start_thread_mailslot (select_record *me, select_stuff *stuff);
struct mailslotinf
{
cygthread *thread;
bool stop_thread_mailslot;
select_record *start;
};
static DWORD WINAPI
thread_mailslot (void *arg)
{
mailslotinf *mi = (mailslotinf *) arg;
select_mailslot_info *mi = (select_mailslot_info *) arg;
bool gotone = false;
DWORD sleep_time = 0;
@ -1587,14 +1613,14 @@ thread_mailslot (void *arg)
{
if (peek_mailslot (s, true))
gotone = true;
if (mi->stop_thread_mailslot)
if (mi->stop_thread)
{
select_printf ("stopping");
goto out;
}
}
/* Paranoid check */
if (mi->stop_thread_mailslot)
if (mi->stop_thread)
{
select_printf ("stopping from outer loop");
break;
@ -1614,27 +1640,27 @@ start_thread_mailslot (select_record *me, select_stuff *stuff)
{
if (stuff->device_specific_mailslot)
{
me->h = *((mailslotinf *) stuff->device_specific_mailslot)->thread;
me->h = *((select_mailslot_info *) stuff->device_specific_mailslot)->thread;
return 1;
}
mailslotinf *mi = new mailslotinf;
select_mailslot_info *mi = new select_mailslot_info;
mi->start = &stuff->start;
mi->stop_thread_mailslot = false;
mi->stop_thread = false;
mi->thread = new cygthread (thread_mailslot, 0, mi, "select_mailslot");
me->h = *mi->thread;
if (!me->h)
return 0;
stuff->device_specific_mailslot = (void *) mi;
stuff->device_specific_mailslot = mi;
return 1;
}
static void
mailslot_cleanup (select_record *, select_stuff *stuff)
{
mailslotinf *mi = (mailslotinf *) stuff->device_specific_mailslot;
select_mailslot_info *mi = (select_mailslot_info *) stuff->device_specific_mailslot;
if (mi && mi->thread)
{
mi->stop_thread_mailslot = true;
mi->stop_thread = true;
mi->thread->detach ();
delete mi;
stuff->device_specific_mailslot = NULL;
@ -1642,10 +1668,9 @@ mailslot_cleanup (select_record *, select_stuff *stuff)
}
select_record *
fhandler_mailslot::select_read (select_record *s)
fhandler_mailslot::select_read (select_stuff *ss)
{
if (!s)
s = new select_record;
select_record *s = ss->start.next;
s->startup = start_thread_mailslot;
s->peek = peek_mailslot;
s->verify = verify_mailslot;

98
winsup/cygwin/select.h Normal file
View File

@ -0,0 +1,98 @@
/* select.h
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
2005, 2006, 2007, 2008, 2009 Red Hat, Inc.
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. */
#ifndef _SELECT_H_
#define _SELECT_H_
struct select_record
{
int fd;
HANDLE h;
fhandler_base *fh;
int thread_errno;
bool windows_handle;
bool read_ready, write_ready, except_ready;
bool read_selected, write_selected, except_selected;
bool except_on_write;
int (*startup) (select_record *me, class select_stuff *stuff);
int (*peek) (select_record *, bool);
int (*verify) (select_record *me, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds);
void (*cleanup) (select_record *me, class select_stuff *stuff);
struct select_record *next;
void set_select_errno () {__seterrno (); thread_errno = errno;}
int saw_error () {return thread_errno;}
select_record () {}
select_record (int): fd (0), h (NULL), fh (NULL), thread_errno (0),
windows_handle (false), read_ready (false), write_ready (false),
except_ready (false), read_selected (false), write_selected (false),
except_selected (false), except_on_write (false),
startup (NULL), peek (NULL), verify (NULL), cleanup (NULL),
next (NULL) {}
};
struct select_info
{
cygthread *thread;
bool stop_thread;
select_record *start;
select_info () {}
};
struct select_pipe_info: public select_info
{
DWORD n;
HANDLE w4[MAXIMUM_WAIT_OBJECTS];
select_pipe_info ();
~select_pipe_info ();
void add_watch_handle (fhandler_pipe *);
};
struct select_socket_info: public select_info
{
int max_w4;
int num_w4;
LONG *ser_num;
HANDLE *w4;
};
struct select_serial_info: public select_info
{
};
struct select_mailslot_info: public select_info
{
};
class select_stuff
{
public:
~select_stuff ();
bool always_ready, windows_used;
select_record start;
select_pipe_info *device_specific_pipe;
select_socket_info *device_specific_socket;
select_serial_info *device_specific_serial;
select_mailslot_info *device_specific_mailslot;
bool test_and_set (int i, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds);
int poll (fd_set *readfds, fd_set *writefds, fd_set *exceptfds);
int wait (fd_set *readfds, fd_set *writefds, fd_set *exceptfds, DWORD ms);
void cleanup ();
select_stuff (): always_ready (0), windows_used (0), start (0),
device_specific_pipe (0),
device_specific_socket (0),
device_specific_serial (0),
device_specific_mailslot (0) {}
};
#endif /* _SELECT_H_ */

View File

@ -151,7 +151,7 @@ __db_mbtowc (struct _reent *r, wchar_t *pwc, const char *s, size_t n, UINT cp,
if (n == 0)
return -2;
if (pwc == NULL)
pwc = &dummy;
@ -221,7 +221,7 @@ __eucjp_mbtowc (struct _reent *r, wchar_t *pwc, const char *s, size_t n,
if (n == 0)
return -2;
if (pwc == NULL)
pwc = &dummy;
@ -437,7 +437,7 @@ sys_cp_wcstombs (wctomb_p f_wctomb, char *charset, char *dst, size_t len,
bytes = 1;
}
else if (bytes == -1 && *charset != 'U'/*TF-8*/)
{
{
/* Convert chars invalid in the current codepage to a sequence
ASCII SO; UTF-8 representation of invalid char. */
buf[0] = 0x0e; /* ASCII SO */
@ -460,20 +460,20 @@ sys_cp_wcstombs (wctomb_p f_wctomb, char *charset, char *dst, size_t len,
}
bytes += __utf8_wctomb (_REENT, buf + bytes, *pwcs, charset, &ps);
}
}
}
if (n + bytes <= len)
{
n += bytes;
if (dst)
{
for (int i = 0; i < bytes; ++i)
*ptr++ = buf[i];
}
if (*pwcs++ == 0x00)
{
n += bytes;
if (dst)
{
for (int i = 0; i < bytes; ++i)
*ptr++ = buf[i];
}
if (*pwcs++ == 0x00)
break;
}
}
else
break;
break;
}
if (n && dst)
{
@ -558,10 +558,10 @@ sys_cp_mbstowcs (mbtowc_p f_mbtowc, char *charset, wchar_t *dst, size_t dlen,
if (bytes < 0)
{
/* Invalid UTF-8 sequence? Treat the ASCII SO character as
stand-alone ASCII SO char. */
stand-alone ASCII SO char. */
bytes = 1;
if (dst)
*ptr = 0x0e;
*ptr = 0x0e;
memset (&ps, 0, sizeof ps);
break;
}
@ -602,13 +602,13 @@ sys_cp_mbstowcs (mbtowc_p f_mbtowc, char *charset, wchar_t *dst, size_t dlen,
}
if (bytes > 0)
{
pmbs += bytes;
nms -= bytes;
++count;
{
pmbs += bytes;
nms -= bytes;
++count;
ptr = dst ? ptr + 1 : NULL;
--len;
}
--len;
}
else
{
if (bytes == 0)

View File

@ -547,7 +547,7 @@ unlink_nt (path_conv &pc)
way (for instance, font files) by setting the delete disposition fails
with STATUS_CANNOT_DELETE. Strange enough, deleting these hardlinks
using delete-on-close semantic works... most of the time.
Don't use delete-on-close on remote shares. If two processes
have open handles on a file and one of them calls unlink, the
file is removed from the remote share even though the other
@ -556,7 +556,7 @@ unlink_nt (path_conv &pc)
Microsoft KB 837665 describes this problem as a bug in 2K3, but
I have reproduced it on other systems. */
if (status == STATUS_CANNOT_DELETE && !pc.isremote ())
{
{
HANDLE fh2;
UNICODE_STRING fname;
@ -573,11 +573,11 @@ unlink_nt (path_conv &pc)
syscall_printf ("Setting delete-on-close failed, status = %p",
status);
/* This is really the last chance. If it hasn't been moved
to the bin already, try it now. If moving to the bin
to the bin already, try it now. If moving to the bin
succeeds, we got rid of the file in some way, even if
unlinking didn't work. */
if (bin_stat == dont_move)
bin_stat = try_to_bin (pc, fh, access);
bin_stat = try_to_bin (pc, fh, access);
if (bin_stat == has_been_moved)
status = STATUS_SUCCESS;
}
@ -1563,7 +1563,7 @@ static void
start_transaction (HANDLE &old_trans, HANDLE &trans)
{
NTSTATUS status = NtCreateTransaction (&trans,
SYNCHRONIZE | TRANSACTION_ALL_ACCESS,
SYNCHRONIZE | TRANSACTION_ALL_ACCESS,
NULL, NULL, NULL, 0, 0, 0, NULL, NULL);
if (NT_SUCCESS (status))
{

View File

@ -98,7 +98,7 @@ class pinfo;
#define PTHREAD_RWLOCK_MAGIC PTHREAD_MAGIC+9
#define PTHREAD_RWLOCKATTR_MAGIC PTHREAD_MAGIC+10
#define MUTEX_OWNER_ANONYMOUS ((pthread_t) -1)
#define MUTEX_OWNER_ANONYMOUS ((pthread_t) -1)
/* verifyable_object should not be defined here - it's a general purpose class */