summaryrefslogtreecommitdiffstats
path: root/winsup/cygwin
diff options
context:
space:
mode:
Diffstat (limited to 'winsup/cygwin')
-rw-r--r--winsup/cygwin/ChangeLog131
-rw-r--r--winsup/cygwin/dtable.cc10
-rw-r--r--winsup/cygwin/fhandler.cc120
-rw-r--r--winsup/cygwin/fhandler.h53
-rw-r--r--winsup/cygwin/fhandler_fifo.cc5
-rw-r--r--winsup/cygwin/fhandler_tty.cc64
-rw-r--r--winsup/cygwin/include/sys/strace.h3
-rw-r--r--winsup/cygwin/nlsfuncs.cc27
-rw-r--r--winsup/cygwin/pipe.cc14
-rw-r--r--winsup/cygwin/select.cc145
-rw-r--r--winsup/cygwin/select.h7
-rw-r--r--winsup/cygwin/sigproc.cc1
-rw-r--r--winsup/cygwin/strace.cc3
-rw-r--r--winsup/cygwin/syscalls.cc2
14 files changed, 401 insertions, 184 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 3224cf62e..b2c9203a9 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,127 @@
+2010-04-02 Christopher Faylor <me+cygwin@cgf.cx>
+
+ * fhandler.h (fhandler_base::has_ongoing_io): Declare virtual method.
+ * select.cc (peek_pipe): Reorganize slightly. Don't attempt to check a
+ handle if it has ongoing I/O.
+ (select_pipe_info::select_pipe_info): Delete definition.
+ (select_pipe_info::~select_pipe_info): Delete definition.
+ (thread_pipe): Get rid of WFMO call. Reorganize loop.
+ (pipe_cleanup): Remove dependence on destructor.
+ (thread_serial): Reorganize loop.
+ * select.h (select_pipe_info): Empty this class since it no longer has
+ any special requirements (for now).
+
+ * syscalls.cc (readv): Remove an unneeded debug printf.
+
+2010-04-02 Christopher Faylor <me+cygwin@cgf.cx>
+
+ * fhandler.h (fhandler_base::setup_overlapped): Delete virtual
+ declaration.
+ (fhandler_base::destroy_overlapped): Ditto.
+ (fhandler_base_overlapped): Remove now-unneeded friend.
+ (fhandler_base_overlapped::setup_overlapped): Return int, remove
+ parameter.
+ (fhandler_base_overlapped::get_overlapped): Return reference.
+ (fhandler_base_overlapped::fhandler_base_overlapped): Be more assertive
+ about zeroing everything.
+ (fhandler_base_overlapped::fixup_after_fork): Declare new function.
+ (fhandler_base_overlapped::fixup_after_exec): Ditto.
+ (fhandler_base_overlapped::dup): Ditto.
+ (fhandler_base_overlapped::close): Ditto.
+ * fhandler_fifo.cc (fhandler_fifo::dup): Call
+ fhandler_base_overlapped::dup rather than fhandler_base::dup.
+ * pipe.cc (fhandler_pipe::dup): Ditto.
+ (fhandler_pipe::init): Accommodate change in setup_overlapped arguments
+ for "opened_properly" case.
+
+2010-04-02 Christopher Faylor <me+cygwin@cgf.cx>
+
+ * fhandler_fifo.cc (fhandler_fifo::fhandler_fifo): Properly initialize
+ overlapped part of this class.
+
+2010-04-02 Corinna Vinschen <corinna@vinschen.de>
+
+ * fhandler_tty.cc (fhandler_tty_slave::close): Revert previous change.
+
+2010-04-02 Christopher Faylor <me+cygwin@cgf.cx>
+
+ * select.h (select_pipe_info::add_watch_handle): Delete declaration.
+ * select.cc (select_pipe_info::add_watch_handle): Delete definition.
+ (fhandler_pipe::select_read): Delete call to add_watch_handle.
+ (fhandler_pipe::select_write): Ditto.
+ (fhandler_pipe::select_except): Ditto.
+
+2010-04-02 Christopher Faylor <me+cygwin@cgf.cx>
+
+ * dtable.cc (dtable::init_std_file_from_handle): Avoid adding fh to
+ fdtab until we know that it is good.
+ * fhandler_tty.cc (fhandler_tty_slave::fhandler_tty_slave): Handle
+ error conditions more consistently. Avoid handle leakage on error.
+
+2010-04-02 Corinna Vinschen <corinna@vinschen.de>
+
+ * fhandler_tty.cc (fhandler_tty_slave::close): Avoid potential crash
+ if former open call has been unsuccessful.
+
+2010-04-01 Corinna Vinschen <corinna@vinschen.de>
+
+ * nlsfuncs.cc: Fix indentation.
+
+2010-04-01 Corinna Vinschen <corinna@vinschen.de>
+
+ * nlsfuncs.cc (rebase_locale_buf): New helper function to rebase
+ function pointers in locale structures. Explain why this is necessary.
+ (__set_lc_time_from_win): Use rebase_locale_buf after realloc.
+ (__set_lc_numeric_from_win): Ditto.
+ (__set_lc_monetary_from_win): Ditto.
+
+2010-03-31 Christopher Faylor <me+cygwin@cgf.cx>
+
+ * sigproc.cc (wait_sig): Make sure that strace is activated on
+ __SIGSTRACE by calling new strace::activate function.
+ * strace.cc (strace::activate): Rename from strace::strace.
+ * strace.h (strace::activate): Define new function.
+ (strace::strace): Call activate.
+
+2010-03-31 Christopher Faylor <me+cygwin@cgf.cx>
+
+ * fhandler.h (fhandler_base_overlapped): Temporarily (?) make
+ select_pipe_info a friend until the fhandler_tty intertangling can be
+ worked out.
+ * select.cc (select_pipe_info::add_watch_handle): Don't inspect the
+ overlapped event if we're not waiting for I/O.
+ (fhandler_tty_common::select_*): Change to standard function. Don't do
+ kludgy fhandler_pipe coercion.
+
+2010-03-31 Christopher Faylor <me+cygwin@cgf.cx>
+
+ * fhandler.cc (fhandler_base::dup): Call setup_overlapped
+ unconditionally.
+ (fhandler_base::fork_fixup): Ditto.
+ (fhandler_base::fixup_after_fork): Ditto.
+ (fhandler_base::fixup_after_exec): Ditto.
+ (fhandler_base_overlapped::setup_overlapped): Move to this class from
+ fhandler_base.
+ (handler_base_overlapped::destroy_overlapped): Ditto.
+ (fhandler_base_overlapped::wait_overlapped): Ditto. Track when we
+ expect pending I/O.
+ (fhandler_base_overlapped::read_overlapped): Move to this class from
+ fhandler_base. Return error if ongoing I/O.
+ (fhandler_base_overlapped::write_overlapped): Ditto.
+ (fhandler_base_overlapped::has_ongoing_io): Semi-reinstate previous
+ function.
+ * fhandler.h (fhandler_base::wait_overlapped): Move to
+ fhandler_base_overlapped class.
+ (fhandler_base::write_overlapped): Ditto.
+ (fhandler_base::get_overlapped): Ditto.
+ (fhandler_base::get_overlapped_buffer): Ditto.
+ (fhandler_base_overlapped): New class.
+ (fhandler_pipe): Inherit from fhandler_base_overlapped. Remove
+ overlapped stuff as a result.
+ (fhandler_fifo): Ditto.
+ * pipe.cc (fhandler_pipe::fhandler_pipe): Initialize fhandler_base_overlapped.
+ (pipe): Put a descriptive name in the fhandler.
+
2010-03-30 Corinna Vinschen <corinna@vinschen.de>
* fhandler_socket.cc (fhandler_socket::wait_for_events): Remove call to
@@ -5,11 +129,12 @@
2010-03-30 Thomas Wolff <towo@towo.net>
- * fhandler.h (class dev_console): Drop vt100_graphics_mode_active.
- Add flags vt100_graphics_mode_G0, vt100_graphics_mode_G1 and
- iso_2022_G1.
+ * fhandler.h (class dev_console): Drop vt100_graphics_mode_active. Add
+ flags vt100_graphics_mode_G0, vt100_graphics_mode_G1 and iso_2022_G1.
* fhandler_console.cc: Throughout, tune VT100 graphics mode switching
to follow ISO 2022 strictly.
+ (fhandler_console::write) Reset VT100 graphic mode flags on terminal
+ full reset (ESC c).
2010-03-30 Corinna Vinschen <corinna@vinschen.de>
diff --git a/winsup/cygwin/dtable.cc b/winsup/cygwin/dtable.cc
index f0738adc2..2076ac998 100644
--- a/winsup/cygwin/dtable.cc
+++ b/winsup/cygwin/dtable.cc
@@ -350,9 +350,6 @@ dtable::init_std_file_from_handle (int fd, HANDLE handle)
else
fh = build_fh_name (name);
- if (fh)
- cygheap->fdtab[fd] = fh;
-
if (name[0])
{
bin = fh->pc_binmode ();
@@ -389,11 +386,12 @@ dtable::init_std_file_from_handle (int fd, HANDLE handle)
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. */
- if (fh->init (dev == FH_CONSOLE && wincap.has_console_handle_problem ()
+ if (!fh->init (dev == FH_CONSOLE && wincap.has_console_handle_problem ()
? INVALID_HANDLE_VALUE : handle, access, bin))
- set_std_handle (fd);
- else
api_fatal ("couldn't initialize fd %d for %s", fd, fh->get_name ());
+
+ cygheap->fdtab[fd] = fh;
+ set_std_handle (fd);
paranoid_printf ("fd %d, handle %p", fd, handle);
}
}
diff --git a/winsup/cygwin/fhandler.cc b/winsup/cygwin/fhandler.cc
index 0e0981fdc..714c46ad0 100644
--- a/winsup/cygwin/fhandler.cc
+++ b/winsup/cygwin/fhandler.cc
@@ -1037,10 +1037,17 @@ fhandler_base::close ()
__seterrno ();
}
- destroy_overlapped ();
return res;
}
+
+int
+fhandler_base_overlapped::close ()
+{
+ destroy_overlapped ();
+ return fhandler_base::close ();
+}
+
int
fhandler_base::ioctl (unsigned int cmd, void *buf)
{
@@ -1162,11 +1169,17 @@ fhandler_base::dup (fhandler_base *child)
VerifyHandle (nh);
child->set_io_handle (nh);
}
- if (get_overlapped ())
- child->setup_overlapped ();
return 0;
}
+int
+fhandler_base_overlapped::dup (fhandler_base *child)
+{
+ int res = fhandler_base::dup (child) ||
+ ((fhandler_base_overlapped *) child)->setup_overlapped ();
+ return res;
+}
+
int fhandler_base::fcntl (int cmd, void *arg)
{
int res;
@@ -1335,8 +1348,6 @@ fhandler_base::fork_fixup (HANDLE parent, HANDLE &h, const char *name)
VerifyHandle (h);
res = true;
}
- if (get_overlapped ())
- setup_overlapped ();
return res;
}
@@ -1355,22 +1366,31 @@ fhandler_base::fixup_after_fork (HANDLE parent)
debug_printf ("inheriting '%s' from parent", get_name ());
if (!nohandle ())
fork_fixup (parent, io_handle, "io_handle");
- if (get_overlapped ())
- setup_overlapped ();
/* POSIX locks are not inherited across fork. */
if (unique_id)
del_my_locks (after_fork);
}
void
+fhandler_base_overlapped::fixup_after_fork (HANDLE parent)
+{
+ setup_overlapped ();
+ fhandler_base::fixup_after_fork (parent);
+}
+
+void
fhandler_base::fixup_after_exec ()
{
debug_printf ("here for '%s'", get_name ());
- if (get_overlapped ())
- setup_overlapped ();
if (unique_id && close_on_exec ())
del_my_locks (after_exec);
}
+void
+fhandler_base_overlapped::fixup_after_exec ()
+{
+ setup_overlapped ();
+ fhandler_base::fixup_after_exec ();
+}
bool
fhandler_base::is_nonblocking ()
@@ -1644,27 +1664,18 @@ fhandler_base::fpathconf (int v)
/* Overlapped I/O */
-bool
-fhandler_base::setup_overlapped (bool doit)
+int
+fhandler_base_overlapped::setup_overlapped ()
{
OVERLAPPED *ov = get_overlapped_buffer ();
memset (ov, 0, sizeof (*ov));
- bool res;
- if (doit)
- {
- set_overlapped (ov);
- res = !!(ov->hEvent = CreateEvent (&sec_none_nih, true, true, NULL));
- }
- else
- {
- set_overlapped (NULL);
- res = false;
- }
- return res;
+ set_overlapped (ov);
+ ov->hEvent = CreateEvent (&sec_none_nih, true, true, NULL);
+ return ov->hEvent ? 0 : -1;
}
void
-fhandler_base::destroy_overlapped ()
+fhandler_base_overlapped::destroy_overlapped ()
{
OVERLAPPED *ov = get_overlapped ();
if (ov && ov->hEvent)
@@ -1672,10 +1683,26 @@ fhandler_base::destroy_overlapped ()
CloseHandle (ov->hEvent);
ov->hEvent = NULL;
}
+ io_pending = false;
+ get_overlapped () = NULL;
+}
+
+bool
+fhandler_base_overlapped::has_ongoing_io ()
+{
+ if (!io_pending)
+ return false;
+ if (WaitForSingleObject (get_overlapped ()->hEvent, 0) != WAIT_OBJECT_0)
+ {
+ set_errno (EAGAIN);
+ return true;
+ }
+ io_pending = false;
+ return false;
}
int
-fhandler_base::wait_overlapped (bool inres, bool writing, DWORD *bytes, DWORD len)
+fhandler_base_overlapped::wait_overlapped (bool inres, bool writing, DWORD *bytes, DWORD len)
{
if (!get_overlapped ())
return inres;
@@ -1687,6 +1714,7 @@ fhandler_base::wait_overlapped (bool inres, bool writing, DWORD *bytes, DWORD le
{
if (inres || err == ERROR_IO_PENDING)
{
+ io_pending = err == ERROR_IO_PENDING;
if (writing && !inres)
*bytes = len; /* This really isn't true but it seems like
this is a corner-case for linux's
@@ -1758,32 +1786,38 @@ fhandler_base::wait_overlapped (bool inres, bool writing, DWORD *bytes, DWORD le
}
void __stdcall
-fhandler_base::read_overlapped (void *ptr, size_t& len)
+fhandler_base_overlapped::read_overlapped (void *ptr, size_t& len)
{
DWORD nbytes;
- while (1)
- {
- bool res = ReadFile (get_handle (), ptr, len, &nbytes,
- get_overlapped ());
- int wres = wait_overlapped (res, false, &nbytes);
- if (wres || !_my_tls.call_signal_handler ())
- break;
- }
+ if (has_ongoing_io ())
+ nbytes = (DWORD) -1;
+ else
+ while (1)
+ {
+ bool res = ReadFile (get_handle (), ptr, len, &nbytes,
+ get_overlapped ());
+ int wres = wait_overlapped (res, false, &nbytes);
+ if (wres || !_my_tls.call_signal_handler ())
+ break;
+ }
len = (size_t) nbytes;
}
ssize_t __stdcall
-fhandler_base::write_overlapped (const void *ptr, size_t len)
+fhandler_base_overlapped::write_overlapped (const void *ptr, size_t len)
{
DWORD nbytes;
- while (1)
- {
- bool res = WriteFile (get_output_handle (), ptr, len, &nbytes,
- get_overlapped ());
- int wres = wait_overlapped (res, true, &nbytes, (size_t) len);
- if (wres || !_my_tls.call_signal_handler ())
- break;
- }
+ if (has_ongoing_io ())
+ nbytes = (DWORD) -1;
+ else
+ while (1)
+ {
+ bool res = WriteFile (get_output_handle (), ptr, len, &nbytes,
+ get_overlapped ());
+ int wres = wait_overlapped (res, true, &nbytes, (size_t) len);
+ if (wres || !_my_tls.call_signal_handler ())
+ break;
+ }
debug_printf ("returning %u", nbytes);
return nbytes;
}
diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index 3d1b46bf4..26a7585d7 100644
--- a/winsup/cygwin/fhandler.h
+++ b/winsup/cygwin/fhandler.h
@@ -150,9 +150,6 @@ class fhandler_base
void del_my_locks (del_lock_called_from);
HANDLE read_state;
- int wait_overlapped (bool, bool, DWORD *, DWORD = 0) __attribute__ ((regparm (3)));
- bool setup_overlapped (bool doit = true) __attribute__ ((regparm (2)));
- void destroy_overlapped () __attribute__ ((regparm (1)));
public:
class fhandler_base *archetype;
@@ -310,9 +307,7 @@ class fhandler_base
virtual int fcntl (int cmd, void *);
virtual char const *ttyname () { return get_name (); }
virtual void __stdcall read (void *ptr, size_t& len) __attribute__ ((regparm (3)));
- virtual void __stdcall read_overlapped (void *ptr, size_t& len) __attribute__ ((regparm (3)));
virtual ssize_t __stdcall write (const void *ptr, size_t len);
- virtual ssize_t __stdcall write_overlapped (const void *ptr, size_t len);
virtual ssize_t __stdcall readv (const struct iovec *, int iovcnt, ssize_t tot = -1);
virtual ssize_t __stdcall writev (const struct iovec *, int iovcnt, ssize_t tot = -1);
virtual ssize_t __stdcall pread (void *, size_t, _off64_t) __attribute__ ((regparm (3)));
@@ -354,9 +349,6 @@ class fhandler_base
virtual void __stdcall raw_read (void *ptr, size_t& ulen);
virtual ssize_t __stdcall raw_write (const void *ptr, size_t ulen);
- virtual OVERLAPPED *get_overlapped () {return NULL;}
- virtual OVERLAPPED *get_overlapped_buffer () {return NULL;}
- virtual void set_overlapped (OVERLAPPED *) {}
/* Virtual accessor functions to hide the fact
that some fd's have two handles. */
@@ -394,6 +386,7 @@ class fhandler_base
bool issymlink () {return pc.issymlink ();}
bool device_access_denied (int) __attribute__ ((regparm (2)));
int fhaccess (int flags, bool) __attribute__ ((regparm (3)));
+ virtual bool has_ongoing_io () {return false;}
};
class fhandler_mailslot : public fhandler_base
@@ -558,18 +551,41 @@ class fhandler_socket: public fhandler_base
bool is_slow () {return true;}
};
-class fhandler_pipe: public fhandler_base
+class fhandler_base_overlapped: public fhandler_base
{
-private:
- pid_t popen_pid;
+protected:
+ bool io_pending;
OVERLAPPED io_status;
OVERLAPPED *overlapped;
public:
- fhandler_pipe ();
-
- OVERLAPPED *get_overlapped () {return overlapped;}
+ int wait_overlapped (bool, bool, DWORD *, DWORD = 0) __attribute__ ((regparm (3)));
+ int setup_overlapped () __attribute__ ((regparm (1)));
+ void destroy_overlapped () __attribute__ ((regparm (1)));
+ void __stdcall read_overlapped (void *ptr, size_t& len) __attribute__ ((regparm (3)));
+ ssize_t __stdcall write_overlapped (const void *ptr, size_t len);
+ OVERLAPPED *&get_overlapped () {return overlapped;}
OVERLAPPED *get_overlapped_buffer () {return &io_status;}
void set_overlapped (OVERLAPPED *ov) {overlapped = ov;}
+ fhandler_base_overlapped (): io_pending (false), overlapped (NULL)
+ {
+ memset (&io_status, 0, sizeof io_status);
+ }
+ bool has_ongoing_io ();
+
+ void fixup_after_fork (HANDLE);
+ void fixup_after_exec ();
+
+ int close ();
+ int dup (fhandler_base *child);
+};
+
+class fhandler_pipe: public fhandler_base_overlapped
+{
+private:
+ pid_t popen_pid;
+public:
+ fhandler_pipe ();
+
bool ispipe() const { return true; }
@@ -595,7 +611,7 @@ public:
friend class fhandler_fifo;
};
-class fhandler_fifo: public fhandler_base
+class fhandler_fifo: public fhandler_base_overlapped
{
enum fifo_state
{
@@ -611,7 +627,6 @@ class fhandler_fifo: public fhandler_base
fifo_state wait_state;
HANDLE dummy_client;
HANDLE open_nonserver (const char *, unsigned, LPSECURITY_ATTRIBUTES);
- OVERLAPPED io_status;
bool wait (bool) __attribute__ ((regparm (1)));
char *fifo_name (char *) __attribute__ ((regparm (2)));
public:
@@ -624,8 +639,6 @@ public:
bool isfifo () const { return true; }
void set_close_on_exec (bool val);
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_stuff *);
select_record *select_write (select_stuff *);
select_record *select_except (select_stuff *);
@@ -906,7 +919,9 @@ class dev_console
unsigned rarg;
bool saw_question_mark;
bool saw_greater_than_sign;
- bool vt100_graphics_mode_active;
+ bool vt100_graphics_mode_G0;
+ bool vt100_graphics_mode_G1;
+ bool iso_2022_G1;
bool alternate_charset_active;
bool metabit;
diff --git a/winsup/cygwin/fhandler_fifo.cc b/winsup/cygwin/fhandler_fifo.cc
index b4a78d422..92394dabf 100644
--- a/winsup/cygwin/fhandler_fifo.cc
+++ b/winsup/cygwin/fhandler_fifo.cc
@@ -22,9 +22,8 @@
#include "shared_info.h"
fhandler_fifo::fhandler_fifo ():
- wait_state (fifo_unknown), dummy_client (NULL)
+ fhandler_base_overlapped (), wait_state (fifo_unknown), dummy_client (NULL)
{
- get_overlapped ()->hEvent = NULL;
need_fork_fixup (true);
}
@@ -305,7 +304,7 @@ fhandler_fifo::close ()
int
fhandler_fifo::dup (fhandler_base *child)
{
- int res = fhandler_base::dup (child);
+ int res = fhandler_base_overlapped::dup (child);
fhandler_fifo *fifo_child = (fhandler_fifo *) child;
if (res == 0 && dummy_client)
{
diff --git a/winsup/cygwin/fhandler_tty.cc b/winsup/cygwin/fhandler_tty.cc
index 4e4dc5338..7e8254c3c 100644
--- a/winsup/cygwin/fhandler_tty.cc
+++ b/winsup/cygwin/fhandler_tty.cc
@@ -450,6 +450,20 @@ fhandler_tty_slave::fhandler_tty_slave ()
int
fhandler_tty_slave::open (int flags, mode_t)
{
+ HANDLE tty_owner, from_master_local, to_master_local;
+ HANDLE *handles[] =
+ {
+ &from_master_local, &input_available_event, &input_mutex, &inuse,
+ &ioctl_done_event, &ioctl_request_event, &output_done_event,
+ &output_mutex, &to_master_local, &tty_owner,
+ NULL
+ };
+
+ const char *errmsg = NULL;
+
+ for (HANDLE **h = handles; *h; h++)
+ **h = NULL;
+
if (get_device () == FH_TTY)
dev().tty_to_real_device ();
fhandler_tty_slave *arch = (fhandler_tty_slave *) cygheap->fdtab.find_archetype (pc.dev);
@@ -480,22 +494,19 @@ fhandler_tty_slave::open (int flags, mode_t)
if (!(output_mutex = get_ttyp ()->open_output_mutex ()))
{
- termios_printf ("open output mutex failed, %E");
- __seterrno ();
- return 0;
+ errmsg = "open output mutex failed, %E";
+ goto err;
}
if (!(input_mutex = get_ttyp ()->open_input_mutex ()))
{
- termios_printf ("open input mutex failed, %E");
- __seterrno ();
- return 0;
+ errmsg = "open input mutex failed, %E";
+ goto err;
}
shared_name (buf, INPUT_AVAILABLE_EVENT, get_unit ());
if (!(input_available_event = OpenEvent (EVENT_ALL_ACCESS, TRUE, buf)))
{
- termios_printf ("open input event failed, %E");
- __seterrno ();
- return 0;
+ errmsg = "open input event failed, %E";
+ goto err;
}
/* The ioctl events may or may not exist. See output_done_event,
@@ -515,30 +526,26 @@ fhandler_tty_slave::open (int flags, mode_t)
if (!get_ttyp ()->from_master || !get_ttyp ()->to_master)
{
- termios_printf ("tty handles have been closed");
+ errmsg = "tty handles have been closed";
set_errno (EACCES);
- return 0;
+ goto err_no_errno;
}
- HANDLE from_master_local;
- HANDLE to_master_local;
- from_master_local = to_master_local = NULL;
-
if (cygserver_running == CYGSERVER_UNAVAIL
|| !cygserver_attach_tty (&from_master_local, &to_master_local))
{
if (get_ttyp ()->master_pid < 0)
{
+ errmsg = "*** master is closed";
set_errno (EAGAIN);
- termios_printf ("*** master is closed");
- return 0;
+ goto err_no_errno;
}
pinfo p (get_ttyp ()->master_pid);
if (!p)
{
+ errmsg = "*** couldn't find tty master";
set_errno (EAGAIN);
- termios_printf ("*** couldn't find tty master");
- return 0;
+ goto err_no_errno;
}
termios_printf ("cannot dup handles via server. using old method.");
HANDLE tty_owner = OpenProcess (PROCESS_DUP_HANDLE, FALSE,
@@ -548,7 +555,7 @@ fhandler_tty_slave::open (int flags, mode_t)
termios_printf ("can't open tty (%d) handle process %d",
get_unit (), get_ttyp ()->master_pid);
__seterrno ();
- return 0;
+ goto err_no_msg;
}
if (!DuplicateHandle (tty_owner, get_ttyp ()->from_master,
@@ -558,7 +565,7 @@ fhandler_tty_slave::open (int flags, mode_t)
termios_printf ("can't duplicate input from %u/%p, %E",
get_ttyp ()->master_pid, get_ttyp ()->from_master);
__seterrno ();
- return 0;
+ goto err_no_msg;
}
VerifyHandle (from_master_local);
@@ -566,9 +573,8 @@ fhandler_tty_slave::open (int flags, mode_t)
GetCurrentProcess (), &to_master_local, 0, TRUE,
DUPLICATE_SAME_ACCESS))
{
- termios_printf ("can't duplicate output, %E");
- __seterrno ();
- return 0;
+ errmsg = "can't duplicate output, %E";
+ goto err;
}
VerifyHandle (to_master_local);
CloseHandle (tty_owner);
@@ -601,6 +607,16 @@ out:
myself->set_ctty (get_ttyp (), flags, arch);
return 1;
+
+err:
+ __seterrno ();
+err_no_errno:
+ termios_printf (errmsg);
+err_no_msg:
+ for (HANDLE **h = handles; *h; h++)
+ if (**h && **h != INVALID_HANDLE_VALUE)
+ CloseHandle (**h);
+ return 0;
}
int
diff --git a/winsup/cygwin/include/sys/strace.h b/winsup/cygwin/include/sys/strace.h
index 683cde0a6..376cf7ac6 100644
--- a/winsup/cygwin/include/sys/strace.h
+++ b/winsup/cygwin/include/sys/strace.h
@@ -39,7 +39,8 @@ class strace
void write (unsigned category, const char *buf, int count);
unsigned char _active;
public:
- strace ();
+ void activate ();
+ strace () {activate ();}
int microseconds ();
int version;
int lmicrosec;
diff --git a/winsup/cygwin/nlsfuncs.cc b/winsup/cygwin/nlsfuncs.cc
index 3f2279a18..498b36008 100644
--- a/winsup/cygwin/nlsfuncs.cc
+++ b/winsup/cygwin/nlsfuncs.cc
@@ -325,6 +325,21 @@ locale_cmp (const void *a, const void *b)
return strcmp (*la, *lb);
}
+/* Helper function to workaround reallocs which move blocks even if they shrink.
+ Cygwin's realloc is not doing this, but tcsh's, for instance. All lc_foo
+ structures consist entirely of pointers so they are practically pointer
+ arrays. What we do here is just treat the lc_foo pointers as char ** and
+ rebase all char * pointers within, up to the given size of the structure. */
+static void
+rebase_locale_buf (const void *ptrv, const char *newbase, const char *oldbase,
+ const void *ptrvend)
+{
+ const char **ptrs = (const char **) ptrv;
+ const char **ptrsend = (const char **) ptrvend;
+ while (ptrs < ptrsend)
+ *ptrs++ += newbase - oldbase;
+}
+
static char *
__getlocaleinfo (LCID lcid, LCTYPE type, char **ptr, size_t size,
wctomb_p f_wctomb, const char *charset)
@@ -625,6 +640,9 @@ __set_lc_time_from_win (const char *name, struct lc_time_T *_time_locale,
era = NULL;
else
{
+ if (tmp != new_lc_time_buf)
+ rebase_locale_buf (_time_locale, tmp, new_lc_time_buf,
+ _time_locale + 1);
lc_time_ptr = tmp + (lc_time_ptr - new_lc_time_buf);
new_lc_time_buf = tmp;
lc_time_end = new_lc_time_buf + len;
@@ -674,6 +692,9 @@ __set_lc_time_from_win (const char *name, struct lc_time_T *_time_locale,
free (new_lc_time_buf);
return -1;
}
+ if (tmp != new_lc_time_buf)
+ rebase_locale_buf (_time_locale, tmp, new_lc_time_buf,
+ _time_locale + 1);
if (*lc_time_buf)
free (*lc_time_buf);
*lc_time_buf = tmp;
@@ -717,6 +738,9 @@ __set_lc_numeric_from_win (const char *name,
free (new_lc_numeric_buf);
return -1;
}
+ if (tmp != new_lc_numeric_buf)
+ rebase_locale_buf (_numeric_locale, tmp, new_lc_numeric_buf,
+ _numeric_locale + 1);
if (*lc_numeric_buf)
free (*lc_numeric_buf);
*lc_numeric_buf = tmp;
@@ -816,6 +840,9 @@ __set_lc_monetary_from_win (const char *name,
free (new_lc_monetary_buf);
return -1;
}
+ if (tmp != new_lc_monetary_buf)
+ rebase_locale_buf (_monetary_locale, tmp, new_lc_monetary_buf,
+ _monetary_locale + 1);
if (*lc_monetary_buf)
free (*lc_monetary_buf);
*lc_monetary_buf = tmp;
diff --git a/winsup/cygwin/pipe.cc b/winsup/cygwin/pipe.cc
index 5194856bc..29bd73205 100644
--- a/winsup/cygwin/pipe.cc
+++ b/winsup/cygwin/pipe.cc
@@ -24,7 +24,7 @@ details. */
#include "shared_info.h"
fhandler_pipe::fhandler_pipe ()
- : fhandler_base (), popen_pid (0), overlapped (NULL)
+ : fhandler_base_overlapped (), popen_pid (0)
{
need_fork_fixup (true);
uninterruptible_io (true);
@@ -54,7 +54,10 @@ fhandler_pipe::init (HANDLE f, DWORD a, mode_t mode)
a &= ~FILE_CREATE_PIPE_INSTANCE;
fhandler_base::init (f, a, mode);
close_on_exec (mode & O_CLOEXEC);
- setup_overlapped (opened_properly);
+ if (opened_properly)
+ setup_overlapped ();
+ else
+ destroy_overlapped ();
return 1;
}
@@ -185,7 +188,7 @@ fhandler_pipe::dup (fhandler_base *child)
ftp->set_popen_pid (0);
int res;
- if (get_handle () && fhandler_base::dup (child))
+ if (get_handle () && fhandler_base_overlapped::dup (child))
res = -1;
else
res = 0;
@@ -378,6 +381,11 @@ pipe (int filedes[2])
{
cygheap_fdnew fdin;
cygheap_fdnew fdout (fdin, false);
+ char buf[sizeof ("/dev/fd/pipe:[2147483647]")];
+ __small_sprintf (buf, "/dev/fd/pipe:[%d]", (int) fdin);
+ fhs[0]->pc.set_normalized_path (buf);
+ __small_sprintf (buf, "pipe:[%d]", (int) fdout);
+ fhs[1]->pc.set_normalized_path (buf);
fdin = fhs[0];
fdout = fhs[1];
filedes[0] = fdin;
diff --git a/winsup/cygwin/select.cc b/winsup/cygwin/select.cc
index e1906cb14..41636d179 100644
--- a/winsup/cygwin/select.cc
+++ b/winsup/cygwin/select.cc
@@ -1,7 +1,7 @@
/* select.cc
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
- 2005, 2006, 2007, 2008, 2009 Red Hat, Inc.
+ 2005, 2006, 2007, 2008, 2009, 2010 Red Hat, Inc.
This file is part of Cygwin.
@@ -429,12 +429,17 @@ no_verify (select_record *, fd_set *, fd_set *, fd_set *)
static int
peek_pipe (select_record *s, bool from_select)
{
+ HANDLE h;
+ set_handle_or_return_if_not_open (h, s);
+
int n = 0;
int gotone = 0;
- fhandler_base *fh = s->fh;
+ fhandler_base *fh = (fhandler_base *) s->fh;
- HANDLE h;
- set_handle_or_return_if_not_open (h, s);
+ /* Don't check if this is a non-blocking fd and I/O is still active.
+ That could give a false-positive with peek_pipe and friends. */
+ if (fh->has_ongoing_io ())
+ return 0;
/* Don't perform complicated tests if we don't need to. */
if (!s->read_selected && !s->except_selected)
@@ -577,72 +582,35 @@ out:
static int start_thread_pipe (select_record *me, select_stuff *stuff);
-select_pipe_info::select_pipe_info ()
-{
- n = 1;
- w4[0] = CreateEvent (&sec_none_nih, true, false, NULL);
-}
-
-select_pipe_info::~select_pipe_info ()
-{
- if (thread)
- {
- SetEvent (w4[0]);
- stop_thread = true;
- thread->detach ();
- }
- ForceCloseHandle (w4[0]);
-}
-
-void
-select_pipe_info::add_watch_handle (fhandler_pipe *fh)
-{
- if (fh->get_overlapped () && fh->get_overlapped ()->hEvent)
- w4[n++] = fh->get_overlapped ()->hEvent;
-}
-
static DWORD WINAPI
thread_pipe (void *arg)
{
select_pipe_info *pi = (select_pipe_info *) arg;
- bool gotone = false;
DWORD sleep_time = 0;
+ bool looping = true;
- for (;;)
+ while (looping)
{
- select_record *s = pi->start;
- if (pi->n > 1)
- switch (WaitForMultipleObjects (pi->n, pi->w4, false, INFINITE))
- {
- case WAIT_OBJECT_0:
- goto out;
- default:
- break;
- }
- while ((s = s->next))
+ for (select_record *s = pi->start; (s = s->next); )
if (s->startup == start_thread_pipe)
{
if (peek_pipe (s, true))
- gotone = true;
+ looping = false;
if (pi->stop_thread)
{
select_printf ("stopping");
- goto out;
+ looping = false;
+ break;
}
}
- /* Paranoid check */
- if (pi->stop_thread)
- {
- select_printf ("stopping from outer loop");
- break;
- }
- if (gotone)
+ if (!looping)
break;
Sleep (sleep_time >> 3);
if (sleep_time < 80)
++sleep_time;
+ if (pi->stop_thread)
+ break;
}
-out:
return 0;
}
@@ -667,9 +635,12 @@ start_thread_pipe (select_record *me, select_stuff *stuff)
static void
pipe_cleanup (select_record *, select_stuff *stuff)
{
- if (stuff->device_specific_pipe)
+ select_pipe_info *pi = (select_pipe_info *) stuff->device_specific_pipe;
+ if (pi && pi->thread)
{
- delete stuff->device_specific_pipe;
+ pi->stop_thread = true;
+ pi->thread->detach ();
+ delete pi;
stuff->device_specific_pipe = NULL;
}
}
@@ -691,7 +662,6 @@ fhandler_pipe::select_read (select_stuff *ss)
if (!ss->device_specific_pipe
&& (ss->device_specific_pipe = new select_pipe_info) == NULL)
return NULL;
- ss->device_specific_pipe->add_watch_handle (this);
select_record *s = ss->start.next;
s->startup = start_thread_pipe;
@@ -709,7 +679,6 @@ fhandler_pipe::select_write (select_stuff *ss)
if (!ss->device_specific_pipe
&& (ss->device_specific_pipe = new select_pipe_info) == NULL)
return NULL;
- ss->device_specific_pipe->add_watch_handle (this);
select_record *s = ss->start.next;
s->startup = start_thread_pipe;
s->peek = peek_pipe;
@@ -726,7 +695,6 @@ fhandler_pipe::select_except (select_stuff *ss)
if (!ss->device_specific_pipe
&& (ss->device_specific_pipe = new select_pipe_info) == NULL)
return NULL;
- ss->device_specific_pipe->add_watch_handle (this);
select_record *s = ss->start.next;
s->startup = start_thread_pipe;
s->peek = peek_pipe;
@@ -906,19 +874,50 @@ fhandler_console::select_except (select_stuff *ss)
select_record *
fhandler_tty_common::select_read (select_stuff *ss)
{
- return ((fhandler_pipe *) this)->fhandler_pipe::select_read (ss);
+ if (!ss->device_specific_pipe
+ && (ss->device_specific_pipe = new select_pipe_info) == NULL)
+ return NULL;
+
+ select_record *s = ss->start.next;
+ s->startup = start_thread_pipe;
+ s->peek = peek_pipe;
+ s->verify = verify_ok;
+ s->cleanup = pipe_cleanup;
+ s->read_selected = true;
+ s->read_ready = false;
+ return s;
}
select_record *
fhandler_tty_common::select_write (select_stuff *ss)
{
- return ((fhandler_pipe *) this)->fhandler_pipe::select_write (ss);
+ if (!ss->device_specific_pipe
+ && (ss->device_specific_pipe = new select_pipe_info) == NULL)
+ return NULL;
+ select_record *s = ss->start.next;
+ s->startup = start_thread_pipe;
+ s->peek = peek_pipe;
+ s->verify = verify_ok;
+ s->cleanup = pipe_cleanup;
+ s->write_selected = true;
+ s->write_ready = false;
+ return s;
}
select_record *
fhandler_tty_common::select_except (select_stuff *ss)
{
- return ((fhandler_pipe *) this)->fhandler_pipe::select_except (ss);
+ if (!ss->device_specific_pipe
+ && (ss->device_specific_pipe = new select_pipe_info) == NULL)
+ return NULL;
+ select_record *s = ss->start.next;
+ s->startup = start_thread_pipe;
+ s->peek = peek_pipe;
+ s->verify = verify_ok;
+ s->cleanup = pipe_cleanup;
+ s->except_selected = true;
+ s->except_ready = false;
+ return s;
}
static int
@@ -1098,25 +1097,23 @@ static DWORD WINAPI
thread_serial (void *arg)
{
select_serial_info *si = (select_serial_info *) arg;
- bool gotone = false;
+ bool looping = true;
- for (;;)
- {
- select_record *s = si->start;
- while ((s = s->next))
- if (s->startup == start_thread_serial)
- {
- if (peek_serial (s, true))
- gotone = true;
- }
- if (si->stop_thread)
+ while (looping)
+ for (select_record *s = si->start; (s = s->next); )
+ if (s->startup != start_thread_serial)
+ continue;
+ else
{
- select_printf ("stopping");
- break;
+ if (peek_serial (s, true))
+ looping = false;
+ if (si->stop_thread)
+ {
+ select_printf ("stopping");
+ looping = false;
+ break;
+ }
}
- if (gotone)
- break;
- }
select_printf ("exiting");
return 0;
diff --git a/winsup/cygwin/select.h b/winsup/cygwin/select.h
index 743222ebd..8734b1e04 100644
--- a/winsup/cygwin/select.h
+++ b/winsup/cygwin/select.h
@@ -1,7 +1,7 @@
/* select.h
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
- 2005, 2006, 2007, 2008, 2009 Red Hat, Inc.
+ 2005, 2006, 2007, 2008, 2009, 2010 Red Hat, Inc.
This file is part of Cygwin.
@@ -49,11 +49,6 @@ struct 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
diff --git a/winsup/cygwin/sigproc.cc b/winsup/cygwin/sigproc.cc
index cb70568fa..74e96ce30 100644
--- a/winsup/cygwin/sigproc.cc
+++ b/winsup/cygwin/sigproc.cc
@@ -1224,6 +1224,7 @@ wait_sig (VOID *)
talktome (&pack.si);
break;
case __SIGSTRACE:
+ strace.activate ();
strace.hello ();
break;
case __SIGPENDING:
diff --git a/winsup/cygwin/strace.cc b/winsup/cygwin/strace.cc
index fb62e29dc..beba5b335 100644
--- a/winsup/cygwin/strace.cc
+++ b/winsup/cygwin/strace.cc
@@ -31,7 +31,8 @@ class strace NO_COPY strace;
#ifndef NOSTRACE
-strace::strace ()
+void
+strace::activate ()
{
if (!dynamically_loaded && !_active && being_debugged ())
{
diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc
index 96cf16dde..65bab2b10 100644
--- a/winsup/cygwin/syscalls.cc
+++ b/winsup/cygwin/syscalls.cc
@@ -913,7 +913,7 @@ readv (int fd, const struct iovec *const iov, const int iovcnt)
fd, iov, iovcnt, wait ? "" : "non", sigcatchers);
if (wait && (!cfd->is_slow () || cfd->uninterruptible_io ()))
- debug_printf ("no need to call ready_for_read");
+ /* no need to call ready_for_read */;
else if (!cfd->ready_for_read (fd, wait))
{
res = -1;