* 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> 2009-06-30 Christopher Faylor <me+cygwin@cgf.cx>
* fhandler.cc (fhandler_base::has_ongoing_io): Accept an argument * fhandler.cc (fhandler_base::has_ongoing_io): Accept an argument

View File

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

View File

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

View File

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

View File

@ -37,6 +37,7 @@ extern const char proc[];
extern const int proc_len; extern const int proc_len;
class select_record; class select_record;
class select_stuff;
class fhandler_disk_file; class fhandler_disk_file;
class inode_t; class inode_t;
typedef struct __DIR DIR; typedef struct __DIR DIR;
@ -354,9 +355,9 @@ class fhandler_base
virtual HANDLE& get_io_handle () { return io_handle; } virtual HANDLE& get_io_handle () { return io_handle; }
virtual HANDLE& get_output_handle () { return io_handle; } virtual HANDLE& get_output_handle () { return io_handle; }
virtual bool hit_eof () {return false;} virtual bool hit_eof () {return false;}
virtual select_record *select_read (select_record *s); virtual select_record *select_read (select_stuff *);
virtual select_record *select_write (select_record *s); virtual select_record *select_write (select_stuff *);
virtual select_record *select_except (select_record *s); virtual select_record *select_except (select_stuff *);
virtual int ready_for_read (int fd, DWORD howlong); virtual int ready_for_read (int fd, DWORD howlong);
virtual const char *get_native_name () 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 open (int flags, mode_t mode = 0);
int write (const void *ptr, size_t len); int write (const void *ptr, size_t len);
int ioctl (unsigned int cmd, void *); int ioctl (unsigned int cmd, void *);
select_record *select_read (select_record *s); select_record *select_read (select_stuff *);
}; };
struct wsa_event struct wsa_event
@ -507,9 +508,9 @@ class fhandler_socket: public fhandler_base
void fixup_after_fork (HANDLE); void fixup_after_fork (HANDLE);
char *get_proc_fd_name (char *buf); char *get_proc_fd_name (char *buf);
select_record *select_read (select_record *s); select_record *select_read (select_stuff *);
select_record *select_write (select_record *s); select_record *select_write (select_stuff *);
select_record *select_except (select_record *s); select_record *select_except (select_stuff *);
int ready_for_read (int, DWORD) { return true; } int ready_for_read (int, DWORD) { return true; }
void set_addr_family (int af) {addr_family = af;} void set_addr_family (int af) {addr_family = af;}
int get_addr_family () {return addr_family;} int get_addr_family () {return addr_family;}
@ -543,9 +544,9 @@ public:
void set_popen_pid (pid_t pid) {popen_pid = pid;} void set_popen_pid (pid_t pid) {popen_pid = pid;}
pid_t get_popen_pid () const {return popen_pid;} pid_t get_popen_pid () const {return popen_pid;}
_off64_t lseek (_off64_t offset, int whence); _off64_t lseek (_off64_t offset, int whence);
select_record *select_read (select_record *s); select_record *select_read (select_stuff *);
select_record *select_write (select_record *s); select_record *select_write (select_stuff *);
select_record *select_except (select_record *s); select_record *select_except (select_stuff *);
char *get_proc_fd_name (char *buf); char *get_proc_fd_name (char *buf);
void raw_read (void *ptr, size_t& len); void raw_read (void *ptr, size_t& len);
int raw_write (const void *, size_t); int raw_write (const void *, size_t);
@ -584,9 +585,9 @@ public:
int __stdcall fstatvfs (struct statvfs *buf) __attribute__ ((regparm (2))); int __stdcall fstatvfs (struct statvfs *buf) __attribute__ ((regparm (2)));
OVERLAPPED *get_overlapped () {return &io_status;} OVERLAPPED *get_overlapped () {return &io_status;}
OVERLAPPED *get_overlapped_buffer () {return &io_status;} OVERLAPPED *get_overlapped_buffer () {return &io_status;}
select_record *select_read (select_record *s); select_record *select_read (select_stuff *);
select_record *select_write (select_record *s); select_record *select_write (select_stuff *);
select_record *select_except (select_record *s); select_record *select_except (select_stuff *);
}; };
class fhandler_dev_raw: public fhandler_base class fhandler_dev_raw: public fhandler_base
@ -784,9 +785,9 @@ class fhandler_serial: public fhandler_base
permission checking on pgrps. */ permission checking on pgrps. */
virtual int tcgetpgrp () { return pgrp_; } virtual int tcgetpgrp () { return pgrp_; }
virtual int tcsetpgrp (const pid_t pid) { pgrp_ = pid; return 0; } virtual int tcsetpgrp (const pid_t pid) { pgrp_ = pid; return 0; }
select_record *select_read (select_record *s); select_record *select_read (select_stuff *);
select_record *select_write (select_record *s); select_record *select_write (select_stuff *);
select_record *select_except (select_record *s); select_record *select_except (select_stuff *);
bool is_slow () {return true;} bool is_slow () {return true;}
}; };
@ -964,9 +965,9 @@ class fhandler_console: public fhandler_termios
void init (HANDLE, DWORD, mode_t); void init (HANDLE, DWORD, mode_t);
bool mouse_aware () {return dev_state->use_mouse;} bool mouse_aware () {return dev_state->use_mouse;}
select_record *select_read (select_record *s); select_record *select_read (select_stuff *);
select_record *select_write (select_record *s); select_record *select_write (select_stuff *);
select_record *select_except (select_record *s); select_record *select_except (select_stuff *);
void fixup_after_fork_exec (bool); void fixup_after_fork_exec (bool);
void fixup_after_exec () {fixup_after_fork_exec (true);} void fixup_after_exec () {fixup_after_fork_exec (true);}
void fixup_after_fork (HANDLE) {fixup_after_fork_exec (false);} void fixup_after_fork (HANDLE) {fixup_after_fork_exec (false);}
@ -1006,9 +1007,9 @@ class fhandler_tty_common: public fhandler_termios
int close (); int close ();
_off64_t lseek (_off64_t, int); _off64_t lseek (_off64_t, int);
void set_close_on_exec (bool val); void set_close_on_exec (bool val);
select_record *select_read (select_record *s); select_record *select_read (select_stuff *);
select_record *select_write (select_record *s); select_record *select_write (select_stuff *);
select_record *select_except (select_record *s); select_record *select_except (select_stuff *);
bool is_slow () {return true;} 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_fork (HANDLE parent);
void fixup_after_exec (); void fixup_after_exec ();
select_record *select_read (select_record *s); select_record *select_read (select_stuff *);
int cygserver_attach_tty (HANDLE*, HANDLE*); int cygserver_attach_tty (HANDLE*, HANDLE*);
int get_unit (); int get_unit ();
virtual char const *ttyname () { return pc.dev.name; } virtual char const *ttyname () { return pc.dev.name; }
@ -1090,9 +1091,9 @@ class fhandler_dev_null: public fhandler_base
public: public:
fhandler_dev_null (); fhandler_dev_null ();
select_record *select_read (select_record *s); select_record *select_read (select_stuff *);
select_record *select_write (select_record *s); select_record *select_write (select_stuff *);
select_record *select_except (select_record *s); select_record *select_except (select_stuff *);
}; };
class fhandler_dev_zero: public fhandler_base 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 set_close_on_exec (bool val);
void fixup_after_fork (HANDLE parent); void fixup_after_fork (HANDLE parent);
select_record *select_read (select_record *s); select_record *select_read (select_stuff *);
select_record *select_write (select_record *s); select_record *select_write (select_stuff *);
select_record *select_except (select_record *s); select_record *select_except (select_stuff *);
bool is_slow () {return true;} bool is_slow () {return true;}
}; };
@ -1384,55 +1385,4 @@ typedef union
char __virtual[sizeof (fhandler_virtual)]; char __virtual[sizeof (fhandler_virtual)];
char __windows[sizeof (fhandler_windows)]; char __windows[sizeof (fhandler_windows)];
} fhandler_union; } 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_ */ #endif /* _FHANDLER_H_ */

View File

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

View File

@ -286,7 +286,7 @@ class inode_t
void wait () { ++i_wait; } void wait () { ++i_wait; }
void unwait () { if (i_wait > 0) --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 (); lockf_t *get_all_locks_list ();

View File

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

View File

@ -27,6 +27,7 @@ details. */
#include "security.h" #include "security.h"
#include "path.h" #include "path.h"
#include "fhandler.h" #include "fhandler.h"
#include "select.h"
#include "dtable.h" #include "dtable.h"
#include "cygheap.h" #include "cygheap.h"
#include "pinfo.h" #include "pinfo.h"
@ -68,7 +69,7 @@ typedef long fd_mask;
#define UNIX_FD_ISSET(n, p) \ #define UNIX_FD_ISSET(n, p) \
((p)->fds_bits[(n)/UNIX_NFDBITS] & (1L << ((n) % UNIX_NFDBITS))) ((p)->fds_bits[(n)/UNIX_NFDBITS] & (1L << ((n) % UNIX_NFDBITS)))
#define UNIX_FD_ZERO(p, n) \ #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 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)); #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 */ /* Add a record to the select chain */
int bool
select_stuff::test_and_set (int i, fd_set *readfds, fd_set *writefds, select_stuff::test_and_set (int i, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds) fd_set *exceptfds)
{ {
select_record *s = NULL; if (!UNIX_FD_ISSET (i, readfds) && !UNIX_FD_ISSET (i, writefds)
if (UNIX_FD_ISSET (i, readfds) && (s = cygheap->fdtab.select_read (i, s)) == NULL) && ! UNIX_FD_ISSET (i, exceptfds))
return 0; /* error */ return true;
if (UNIX_FD_ISSET (i, writefds) && (s = cygheap->fdtab.select_write (i, s)) == NULL)
return 0; /* error */ select_record *s = new select_record;
if (UNIX_FD_ISSET (i, exceptfds) && (s = cygheap->fdtab.select_except (i, s)) == NULL) if (!s)
return 0; /* error */ return false;
if (s == NULL)
return 1; /* nothing to do */ 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) if (s->read_ready || s->write_ready || s->except_ready)
always_ready = true; always_ready = true;
@ -225,9 +234,12 @@ select_stuff::test_and_set (int i, fd_set *readfds, fd_set *writefds,
if (s->windows_handle) if (s->windows_handle)
windows_used = true; windows_used = true;
s->next = start.next; return true;
start.next = s;
return 1; err:
start.next = s->next;
delete s;
return false;
} }
/* The heart of select. Waits for an fd to do something interesting. */ /* 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); static int start_thread_pipe (select_record *me, select_stuff *stuff);
struct pipeinf select_pipe_info::select_pipe_info ()
{ {
cygthread *thread; n = 1;
bool stop_thread_pipe; w4[0] = CreateEvent (&sec_none_nih, true, false, NULL);
select_record *start; }
};
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 static DWORD WINAPI
thread_pipe (void *arg) thread_pipe (void *arg)
{ {
pipeinf *pi = (pipeinf *) arg; select_pipe_info *pi = (select_pipe_info *) arg;
bool gotone = false; bool gotone = false;
DWORD sleep_time = 0; DWORD sleep_time = 0;
for (;;) for (;;)
{ {
select_record *s = pi->start; 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)) while ((s = s->next))
if (s->startup == start_thread_pipe) if (s->startup == start_thread_pipe)
{ {
if (peek_pipe (s, true)) if (peek_pipe (s, true))
gotone = true; gotone = true;
if (pi->stop_thread_pipe) if (pi->stop_thread)
{ {
select_printf ("stopping"); select_printf ("stopping");
goto out; goto out;
} }
} }
/* Paranoid check */ /* Paranoid check */
if (pi->stop_thread_pipe) if (pi->stop_thread)
{ {
select_printf ("stopping from outer loop"); select_printf ("stopping from outer loop");
break; break;
@ -613,31 +650,27 @@ out:
static int static int
start_thread_pipe (select_record *me, select_stuff *stuff) 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; pi->start = &stuff->start;
return 1; 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; return 1;
} }
static void static void
pipe_cleanup (select_record *, select_stuff *stuff) pipe_cleanup (select_record *, select_stuff *stuff)
{ {
pipeinf *pi = (pipeinf *) stuff->device_specific_pipe; if (stuff->device_specific_pipe)
if (pi && pi->thread)
{ {
pi->stop_thread_pipe = true; delete stuff->device_specific_pipe;
pi->thread->detach ();
delete pi;
stuff->device_specific_pipe = NULL; stuff->device_specific_pipe = NULL;
} }
} }
@ -654,10 +687,14 @@ fhandler_pipe::ready_for_read (int fd, DWORD howlong)
} }
select_record * select_record *
fhandler_pipe::select_read (select_record *s) fhandler_pipe::select_read (select_stuff *ss)
{ {
if (!s) if (!ss->device_specific_pipe
s = new select_record; && (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->startup = start_thread_pipe;
s->peek = peek_pipe; s->peek = peek_pipe;
s->verify = verify_ok; s->verify = verify_ok;
@ -668,10 +705,13 @@ fhandler_pipe::select_read (select_record *s)
} }
select_record * select_record *
fhandler_pipe::select_write (select_record *s) fhandler_pipe::select_write (select_stuff *ss)
{ {
if (!s) if (!ss->device_specific_pipe
s = new select_record; && (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->startup = start_thread_pipe;
s->peek = peek_pipe; s->peek = peek_pipe;
s->verify = verify_ok; s->verify = verify_ok;
@ -682,10 +722,13 @@ fhandler_pipe::select_write (select_record *s)
} }
select_record * select_record *
fhandler_pipe::select_except (select_record *s) fhandler_pipe::select_except (select_stuff *ss)
{ {
if (!s) if (!ss->device_specific_pipe
s = new select_record; && (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->startup = start_thread_pipe;
s->peek = peek_pipe; s->peek = peek_pipe;
s->verify = verify_ok; s->verify = verify_ok;
@ -696,10 +739,9 @@ fhandler_pipe::select_except (select_record *s)
} }
select_record * select_record *
fhandler_fifo::select_read (select_record *s) fhandler_fifo::select_read (select_stuff *ss)
{ {
if (!s) select_record *s = ss->start.next;
s = new select_record;
s->startup = start_thread_pipe; s->startup = start_thread_pipe;
s->peek = peek_pipe; s->peek = peek_pipe;
s->verify = verify_ok; s->verify = verify_ok;
@ -710,10 +752,9 @@ fhandler_fifo::select_read (select_record *s)
} }
select_record * select_record *
fhandler_fifo::select_write (select_record *s) fhandler_fifo::select_write (select_stuff *ss)
{ {
if (!s) select_record *s = ss->start.next;
s = new select_record;
s->startup = start_thread_pipe; s->startup = start_thread_pipe;
s->peek = peek_pipe; s->peek = peek_pipe;
s->verify = verify_ok; s->verify = verify_ok;
@ -724,10 +765,9 @@ fhandler_fifo::select_write (select_record *s)
} }
select_record * select_record *
fhandler_fifo::select_except (select_record *s) fhandler_fifo::select_except (select_stuff *ss)
{ {
if (!s) select_record *s = ss->start.next;
s = new select_record;
s->startup = start_thread_pipe; s->startup = start_thread_pipe;
s->peek = peek_pipe; s->peek = peek_pipe;
s->verify = verify_ok; s->verify = verify_ok;
@ -804,11 +844,11 @@ verify_console (select_record *me, fd_set *rfds, fd_set *wfds,
select_record * 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->startup = no_startup;
s->verify = verify_console; s->verify = verify_console;
set_cursor_maybe (); set_cursor_maybe ();
@ -822,11 +862,11 @@ fhandler_console::select_read (select_record *s)
} }
select_record * 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->startup = no_startup;
s->verify = no_verify; s->verify = no_verify;
set_cursor_maybe (); set_cursor_maybe ();
@ -839,11 +879,11 @@ fhandler_console::select_write (select_record *s)
} }
select_record * 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->startup = no_startup;
s->verify = no_verify; s->verify = no_verify;
set_cursor_maybe (); set_cursor_maybe ();
@ -856,21 +896,21 @@ fhandler_console::select_except (select_record *s)
} }
select_record * 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 * 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 * 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 static int
@ -883,10 +923,9 @@ verify_tty_slave (select_record *me, fd_set *readfds, fd_set *writefds,
} }
select_record * select_record *
fhandler_tty_slave::select_read (select_record *s) fhandler_tty_slave::select_read (select_stuff *ss)
{ {
if (!s) select_record *s = ss->start.next;
s = new select_record;
s->h = input_available_event; s->h = input_available_event;
s->startup = no_startup; s->startup = no_startup;
s->peek = peek_pipe; s->peek = peek_pipe;
@ -898,11 +937,11 @@ fhandler_tty_slave::select_read (select_record *s)
} }
select_record * 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->startup = no_startup;
s->verify = no_verify; s->verify = no_verify;
} }
@ -913,11 +952,11 @@ fhandler_dev_null::select_read (select_record *s)
} }
select_record * 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->startup = no_startup;
s->verify = no_verify; s->verify = no_verify;
} }
@ -928,11 +967,11 @@ fhandler_dev_null::select_write (select_record *s)
} }
select_record * 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->startup = no_startup;
s->verify = no_verify; 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); static int start_thread_serial (select_record *me, select_stuff *stuff);
struct serialinf
{
cygthread *thread;
bool stop_thread_serial;
select_record *start;
};
static int static int
peek_serial (select_record *s, bool) peek_serial (select_record *s, bool)
{ {
@ -1057,7 +1089,7 @@ err:
static DWORD WINAPI static DWORD WINAPI
thread_serial (void *arg) thread_serial (void *arg)
{ {
serialinf *si = (serialinf *) arg; select_serial_info *si = (select_serial_info *) arg;
bool gotone = false; bool gotone = false;
for (;;) for (;;)
@ -1069,7 +1101,7 @@ thread_serial (void *arg)
if (peek_serial (s, true)) if (peek_serial (s, true))
gotone = true; gotone = true;
} }
if (si->stop_thread_serial) if (si->stop_thread)
{ {
select_printf ("stopping"); select_printf ("stopping");
break; break;
@ -1086,26 +1118,26 @@ static int
start_thread_serial (select_record *me, select_stuff *stuff) start_thread_serial (select_record *me, select_stuff *stuff)
{ {
if (stuff->device_specific_serial) if (stuff->device_specific_serial)
me->h = *((select_serial_info *) stuff->device_specific_serial)->thread;
else
{ {
me->h = *((serialinf *) stuff->device_specific_serial)->thread; select_serial_info *si = new select_serial_info;
return 1; 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; return 1;
} }
static void static void
serial_cleanup (select_record *, select_stuff *stuff) 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) if (si && si->thread)
{ {
si->stop_thread_serial = true; si->stop_thread = true;
si->thread->detach (); si->thread->detach ();
delete si; delete si;
stuff->device_specific_serial = NULL; stuff->device_specific_serial = NULL;
@ -1113,11 +1145,11 @@ serial_cleanup (select_record *, select_stuff *stuff)
} }
select_record * 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->startup = start_thread_serial;
s->verify = verify_ok; s->verify = verify_ok;
s->cleanup = serial_cleanup; s->cleanup = serial_cleanup;
@ -1129,11 +1161,11 @@ fhandler_serial::select_read (select_record *s)
} }
select_record * 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->startup = no_startup;
s->verify = verify_ok; s->verify = verify_ok;
} }
@ -1145,11 +1177,11 @@ fhandler_serial::select_write (select_record *s)
} }
select_record * 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->startup = no_startup;
s->verify = verify_ok; s->verify = verify_ok;
} }
@ -1164,46 +1196,57 @@ int
fhandler_base::ready_for_read (int fd, DWORD howlong) fhandler_base::ready_for_read (int fd, DWORD howlong)
{ {
bool avail = false; bool avail = false;
select_record me (this);
me.fd = fd; select_stuff sel;
while (!avail) 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); select_record *me = sel.start.next;
avail = me.read_ready ?: me.peek (&me, false); while (!avail)
if (fd >= 0 && cygheap->fdtab.not_open (fd))
{ {
set_sig_errno (EBADF); avail = me->read_ready ?: me->peek (me, false);
avail = false;
break;
}
if (howlong != INFINITE) if (fd >= 0 && cygheap->fdtab.not_open (fd))
{ {
if (!avail) set_sig_errno (EBADF);
set_sig_errno (EAGAIN); avail = false;
break; break;
} }
if (WaitForSingleObject (signal_arrived, avail ? 0 : 10) == WAIT_OBJECT_0) if (howlong != INFINITE)
{ {
debug_printf ("interrupted"); if (!avail)
set_sig_errno (EINTR); set_sig_errno (EAGAIN);
avail = false; break;
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; return avail;
} }
select_record * 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->startup = no_startup;
s->verify = verify_ok; s->verify = verify_ok;
} }
@ -1214,11 +1257,11 @@ fhandler_base::select_read (select_record *s)
} }
select_record * 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->startup = no_startup;
s->verify = verify_ok; s->verify = verify_ok;
} }
@ -1229,11 +1272,11 @@ fhandler_base::select_write (select_record *s)
} }
select_record * 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->startup = no_startup;
s->verify = verify_ok; s->verify = verify_ok;
} }
@ -1268,20 +1311,10 @@ peek_socket (select_record *me, bool)
static int start_thread_socket (select_record *, select_stuff *); 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 static DWORD WINAPI
thread_socket (void *arg) 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); DWORD timeout = 64 / (si->max_w4 / MAXIMUM_WAIT_OBJECTS);
bool event = false; bool event = false;
@ -1317,15 +1350,15 @@ out:
static int static int
start_thread_socket (select_record *me, select_stuff *stuff) 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; me->h = *si->thread;
return 1; return 1;
} }
si = new socketinf; si = new select_socket_info;
si->ser_num = (LONG *) malloc (MAXIMUM_WAIT_OBJECTS * sizeof (LONG)); si->ser_num = (LONG *) malloc (MAXIMUM_WAIT_OBJECTS * sizeof (LONG));
si->w4 = (HANDLE *) malloc (MAXIMUM_WAIT_OBJECTS * sizeof (HANDLE)); si->w4 = (HANDLE *) malloc (MAXIMUM_WAIT_OBJECTS * sizeof (HANDLE));
if (!si->ser_num || !si->w4) if (!si->ser_num || !si->w4)
@ -1370,7 +1403,7 @@ start_thread_socket (select_record *me, select_stuff *stuff)
continue_outer_loop: continue_outer_loop:
; ;
} }
stuff->device_specific_socket = (void *) si; stuff->device_specific_socket = si;
si->start = &stuff->start; si->start = &stuff->start;
select_printf ("stuff_start %p", &stuff->start); select_printf ("stuff_start %p", &stuff->start);
si->thread = new cygthread (thread_socket, 0, si, "select_socket"); si->thread = new cygthread (thread_socket, 0, si, "select_socket");
@ -1381,7 +1414,7 @@ start_thread_socket (select_record *me, select_stuff *stuff)
void void
socket_cleanup (select_record *, select_stuff *stuff) 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); select_printf ("si %p si->thread %p", si, si ? si->thread : NULL);
if (si && si->thread) if (si && si->thread)
{ {
@ -1400,11 +1433,11 @@ socket_cleanup (select_record *, select_stuff *stuff)
} }
select_record * 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->startup = start_thread_socket;
s->verify = verify_true; s->verify = verify_true;
s->cleanup = socket_cleanup; s->cleanup = socket_cleanup;
@ -1416,11 +1449,11 @@ fhandler_socket::select_read (select_record *s)
} }
select_record * 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->startup = start_thread_socket;
s->verify = verify_true; s->verify = verify_true;
s->cleanup = socket_cleanup; s->cleanup = socket_cleanup;
@ -1437,11 +1470,11 @@ fhandler_socket::select_write (select_record *s)
} }
select_record * 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->startup = start_thread_socket;
s->verify = verify_true; s->verify = verify_true;
s->cleanup = socket_cleanup; s->cleanup = socket_cleanup;
@ -1482,11 +1515,11 @@ verify_windows (select_record *me, fd_set *rfds, fd_set *wfds,
} }
select_record * 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->startup = no_startup;
} }
s->verify = verify_windows; s->verify = verify_windows;
@ -1499,11 +1532,11 @@ fhandler_windows::select_read (select_record *s)
} }
select_record * 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->startup = no_startup;
s->verify = verify_ok; s->verify = verify_ok;
} }
@ -1516,11 +1549,11 @@ fhandler_windows::select_write (select_record *s)
} }
select_record * 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->startup = no_startup;
s->verify = verify_ok; 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); 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 static DWORD WINAPI
thread_mailslot (void *arg) thread_mailslot (void *arg)
{ {
mailslotinf *mi = (mailslotinf *) arg; select_mailslot_info *mi = (select_mailslot_info *) arg;
bool gotone = false; bool gotone = false;
DWORD sleep_time = 0; DWORD sleep_time = 0;
@ -1587,14 +1613,14 @@ thread_mailslot (void *arg)
{ {
if (peek_mailslot (s, true)) if (peek_mailslot (s, true))
gotone = true; gotone = true;
if (mi->stop_thread_mailslot) if (mi->stop_thread)
{ {
select_printf ("stopping"); select_printf ("stopping");
goto out; goto out;
} }
} }
/* Paranoid check */ /* Paranoid check */
if (mi->stop_thread_mailslot) if (mi->stop_thread)
{ {
select_printf ("stopping from outer loop"); select_printf ("stopping from outer loop");
break; break;
@ -1614,27 +1640,27 @@ start_thread_mailslot (select_record *me, select_stuff *stuff)
{ {
if (stuff->device_specific_mailslot) 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; return 1;
} }
mailslotinf *mi = new mailslotinf; select_mailslot_info *mi = new select_mailslot_info;
mi->start = &stuff->start; mi->start = &stuff->start;
mi->stop_thread_mailslot = false; mi->stop_thread = false;
mi->thread = new cygthread (thread_mailslot, 0, mi, "select_mailslot"); mi->thread = new cygthread (thread_mailslot, 0, mi, "select_mailslot");
me->h = *mi->thread; me->h = *mi->thread;
if (!me->h) if (!me->h)
return 0; return 0;
stuff->device_specific_mailslot = (void *) mi; stuff->device_specific_mailslot = mi;
return 1; return 1;
} }
static void static void
mailslot_cleanup (select_record *, select_stuff *stuff) 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) if (mi && mi->thread)
{ {
mi->stop_thread_mailslot = true; mi->stop_thread = true;
mi->thread->detach (); mi->thread->detach ();
delete mi; delete mi;
stuff->device_specific_mailslot = NULL; stuff->device_specific_mailslot = NULL;
@ -1642,10 +1668,9 @@ mailslot_cleanup (select_record *, select_stuff *stuff)
} }
select_record * select_record *
fhandler_mailslot::select_read (select_record *s) fhandler_mailslot::select_read (select_stuff *ss)
{ {
if (!s) select_record *s = ss->start.next;
s = new select_record;
s->startup = start_thread_mailslot; s->startup = start_thread_mailslot;
s->peek = peek_mailslot; s->peek = peek_mailslot;
s->verify = verify_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) if (n == 0)
return -2; return -2;
if (pwc == NULL) if (pwc == NULL)
pwc = &dummy; pwc = &dummy;
@ -221,7 +221,7 @@ __eucjp_mbtowc (struct _reent *r, wchar_t *pwc, const char *s, size_t n,
if (n == 0) if (n == 0)
return -2; return -2;
if (pwc == NULL) if (pwc == NULL)
pwc = &dummy; pwc = &dummy;
@ -437,7 +437,7 @@ sys_cp_wcstombs (wctomb_p f_wctomb, char *charset, char *dst, size_t len,
bytes = 1; bytes = 1;
} }
else if (bytes == -1 && *charset != 'U'/*TF-8*/) else if (bytes == -1 && *charset != 'U'/*TF-8*/)
{ {
/* Convert chars invalid in the current codepage to a sequence /* Convert chars invalid in the current codepage to a sequence
ASCII SO; UTF-8 representation of invalid char. */ ASCII SO; UTF-8 representation of invalid char. */
buf[0] = 0x0e; /* ASCII SO */ 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); bytes += __utf8_wctomb (_REENT, buf + bytes, *pwcs, charset, &ps);
} }
} }
if (n + bytes <= len) if (n + bytes <= len)
{ {
n += bytes; n += bytes;
if (dst) if (dst)
{ {
for (int i = 0; i < bytes; ++i) for (int i = 0; i < bytes; ++i)
*ptr++ = buf[i]; *ptr++ = buf[i];
} }
if (*pwcs++ == 0x00) if (*pwcs++ == 0x00)
break; break;
} }
else else
break; break;
} }
if (n && dst) 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) if (bytes < 0)
{ {
/* Invalid UTF-8 sequence? Treat the ASCII SO character as /* Invalid UTF-8 sequence? Treat the ASCII SO character as
stand-alone ASCII SO char. */ stand-alone ASCII SO char. */
bytes = 1; bytes = 1;
if (dst) if (dst)
*ptr = 0x0e; *ptr = 0x0e;
memset (&ps, 0, sizeof ps); memset (&ps, 0, sizeof ps);
break; break;
} }
@ -602,13 +602,13 @@ sys_cp_mbstowcs (mbtowc_p f_mbtowc, char *charset, wchar_t *dst, size_t dlen,
} }
if (bytes > 0) if (bytes > 0)
{ {
pmbs += bytes; pmbs += bytes;
nms -= bytes; nms -= bytes;
++count; ++count;
ptr = dst ? ptr + 1 : NULL; ptr = dst ? ptr + 1 : NULL;
--len; --len;
} }
else else
{ {
if (bytes == 0) 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 way (for instance, font files) by setting the delete disposition fails
with STATUS_CANNOT_DELETE. Strange enough, deleting these hardlinks with STATUS_CANNOT_DELETE. Strange enough, deleting these hardlinks
using delete-on-close semantic works... most of the time. using delete-on-close semantic works... most of the time.
Don't use delete-on-close on remote shares. If two processes 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 have open handles on a file and one of them calls unlink, the
file is removed from the remote share even though the other 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 Microsoft KB 837665 describes this problem as a bug in 2K3, but
I have reproduced it on other systems. */ I have reproduced it on other systems. */
if (status == STATUS_CANNOT_DELETE && !pc.isremote ()) if (status == STATUS_CANNOT_DELETE && !pc.isremote ())
{ {
HANDLE fh2; HANDLE fh2;
UNICODE_STRING fname; UNICODE_STRING fname;
@ -573,11 +573,11 @@ unlink_nt (path_conv &pc)
syscall_printf ("Setting delete-on-close failed, status = %p", syscall_printf ("Setting delete-on-close failed, status = %p",
status); status);
/* This is really the last chance. If it hasn't been moved /* 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 succeeds, we got rid of the file in some way, even if
unlinking didn't work. */ unlinking didn't work. */
if (bin_stat == dont_move) 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) if (bin_stat == has_been_moved)
status = STATUS_SUCCESS; status = STATUS_SUCCESS;
} }
@ -1563,7 +1563,7 @@ static void
start_transaction (HANDLE &old_trans, HANDLE &trans) start_transaction (HANDLE &old_trans, HANDLE &trans)
{ {
NTSTATUS status = NtCreateTransaction (&trans, NTSTATUS status = NtCreateTransaction (&trans,
SYNCHRONIZE | TRANSACTION_ALL_ACCESS, SYNCHRONIZE | TRANSACTION_ALL_ACCESS,
NULL, NULL, NULL, 0, 0, 0, NULL, NULL); NULL, NULL, NULL, 0, 0, 0, NULL, NULL);
if (NT_SUCCESS (status)) if (NT_SUCCESS (status))
{ {

View File

@ -98,7 +98,7 @@ class pinfo;
#define PTHREAD_RWLOCK_MAGIC PTHREAD_MAGIC+9 #define PTHREAD_RWLOCK_MAGIC PTHREAD_MAGIC+9
#define PTHREAD_RWLOCKATTR_MAGIC PTHREAD_MAGIC+10 #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 */ /* verifyable_object should not be defined here - it's a general purpose class */