* fhandler.h (fhandler_pty_common::bytes_available): Declare new function.

(fhandler_pty_master::flush_to_slave): Ditto.
* fhandler_tty.cc (bytes_available): Define new function.
(fhandler_pty_common::bytes_available): Ditto.
(handler_pty_master::flush_to_slave): Ditto.
(fhandler_pty_master::process_slave_output): Call flush_to_slave () here.  Use
bytes_available () rather than PeekNamedPipe.  Cleanup sloppy logic.
(fhandler_pty_slave::read): Use bytes_available () rather than PeekNamedPipe.
(fhandler_pty_slave::ioctl): Ditto.
(fhandler_pty_master::ioctl): Ditto.
(fhandler_pty_master::cleanup): Remove ancient #if 0.
* select.cc (peek_pipe): Call flush_to_slave whenever we're checking for a pty
master.
This commit is contained in:
Christopher Faylor 2012-04-05 02:54:51 +00:00
parent ffcd2c3f89
commit 7b03b0d8ce
4 changed files with 99 additions and 71 deletions

View File

@ -1,3 +1,22 @@
2012-04-04 Christopher Faylor <me.cygwin2012@cgf.cx>
* fhandler.h (fhandler_pty_common::bytes_available): Declare new
function.
(fhandler_pty_master::flush_to_slave): Ditto.
* fhandler_tty.cc (bytes_available): Define new function.
(fhandler_pty_common::bytes_available): Ditto.
(handler_pty_master::flush_to_slave): Ditto.
(fhandler_pty_master::process_slave_output): Call flush_to_slave ()
here. Use bytes_available () rather than PeekNamedPipe. Cleanup
sloppy logic.
(fhandler_pty_slave::read): Use bytes_available () rather than
PeekNamedPipe.
(fhandler_pty_slave::ioctl): Ditto.
(fhandler_pty_master::ioctl): Ditto.
(fhandler_pty_master::cleanup): Remove ancient #if 0.
* select.cc (peek_pipe): Call flush_to_slave whenever we're checking
for a pty master.
2012-04-04 Corinna Vinschen <corinna@vinschen.de> 2012-04-04 Corinna Vinschen <corinna@vinschen.de>
* fhandler_nodevice.cc (fhandler_nodevice::open): Convert EROFS to * fhandler_nodevice.cc (fhandler_nodevice::open): Convert EROFS to

View File

@ -1433,6 +1433,7 @@ class fhandler_pty_common: public fhandler_termios
int close (); int close ();
_off64_t lseek (_off64_t, int); _off64_t lseek (_off64_t, int);
bool bytes_available (DWORD& n);
void set_close_on_exec (bool val); void set_close_on_exec (bool val);
select_record *select_read (select_stuff *); select_record *select_read (select_stuff *);
select_record *select_write (select_stuff *); select_record *select_write (select_stuff *);
@ -1549,6 +1550,7 @@ public:
void fixup_after_fork (HANDLE parent); void fixup_after_fork (HANDLE parent);
void fixup_after_exec (); void fixup_after_exec ();
int tcgetpgrp (); int tcgetpgrp ();
void flush_to_slave ();
fhandler_pty_master (void *) {} fhandler_pty_master (void *) {}
~fhandler_pty_master (); ~fhandler_pty_master ();

View File

@ -50,6 +50,25 @@ fhandler_pty_slave::get_unit ()
return dev ().get_minor (); return dev ().get_minor ();
} }
bool
bytes_available (DWORD& n, HANDLE h)
{
bool succeeded = PeekNamedPipe (h, NULL, 0, NULL, &n, NULL);
if (!succeeded)
{
termios_printf ("PeekNamedPipe(%p) failed, %E", h);
n = 0;
}
debug_only_printf ("%u bytes available", n);
return succeeded;
}
bool
fhandler_pty_common::bytes_available (DWORD &n)
{
return ::bytes_available (n, get_handle ());
}
#ifdef DEBUGGING #ifdef DEBUGGING
static class mutex_stack static class mutex_stack
{ {
@ -62,6 +81,13 @@ public:
static int osi; static int osi;
#endif /*DEBUGGING*/ #endif /*DEBUGGING*/
void
fhandler_pty_master::flush_to_slave ()
{
if (get_readahead_valid () && !(get_ttyp ()->ti.c_lflag & ICANON))
accept_input ();
}
DWORD DWORD
fhandler_pty_common::__acquire_output_mutex (const char *fn, int ln, fhandler_pty_common::__acquire_output_mutex (const char *fn, int ln,
DWORD ms) DWORD ms)
@ -194,6 +220,8 @@ fhandler_pty_master::process_slave_output (char *buf, size_t len, int pktmode_on
int column = 0; int column = 0;
int rc = 0; int rc = 0;
flush_to_slave ();
if (len == 0) if (len == 0)
goto out; goto out;
@ -210,7 +238,6 @@ fhandler_pty_master::process_slave_output (char *buf, size_t len, int pktmode_on
goto out; goto out;
} }
for (;;) for (;;)
{ {
/* Set RLEN to the number of bytes to read from the pipe. */ /* Set RLEN to the number of bytes to read from the pipe. */
@ -226,22 +253,12 @@ fhandler_pty_master::process_slave_output (char *buf, size_t len, int pktmode_on
if (rlen > sizeof outbuf) if (rlen > sizeof outbuf)
rlen = sizeof outbuf; rlen = sizeof outbuf;
HANDLE handle = get_io_handle (); n = 0;
for (;;)
n = 0; // get_readahead_into_buffer (outbuf, len);
if (!n)
{ {
/* Doing a busy wait like this is quite inefficient, but nothing if (!bytes_available (n))
else seems to work completely. Windows should provide some sort
of overlapped I/O for pipes, or something, but it doesn't. */
while (1)
{
if (!PeekNamedPipe (handle, NULL, 0, NULL, &n, NULL))
{
termios_printf ("PeekNamedPipe(%p) failed, %E", handle);
goto err; goto err;
} if (n)
if (n > 0)
break; break;
if (hit_eof ()) if (hit_eof ())
goto out; goto out;
@ -263,14 +280,14 @@ fhandler_pty_master::process_slave_output (char *buf, size_t len, int pktmode_on
rc = -1; rc = -1;
goto out; goto out;
} }
flush_to_slave ();
} }
if (!ReadFile (handle, outbuf, rlen, &n, NULL)) if (!ReadFile (get_handle (), outbuf, rlen, &n, NULL))
{ {
termios_printf ("ReadFile failed, %E"); termios_printf ("ReadFile failed, %E");
goto err; goto err;
} }
}
termios_printf ("bytes read %u", n); termios_printf ("bytes read %u", n);
get_ttyp ()->write_error = 0; get_ttyp ()->write_error = 0;
@ -668,7 +685,6 @@ fhandler_pty_slave::read (void *ptr, size_t& len)
size_t readlen; size_t readlen;
DWORD bytes_in_pipe; DWORD bytes_in_pipe;
char buf[INP_BUFFER_SIZE]; char buf[INP_BUFFER_SIZE];
char peek_buf[INP_BUFFER_SIZE];
DWORD time_to_wait; DWORD time_to_wait;
bg_check_types bg = bg_check (SIGTTIN); bg_check_types bg = bg_check (SIGTTIN);
@ -785,12 +801,8 @@ fhandler_pty_slave::read (void *ptr, size_t& len)
} }
goto out; goto out;
} }
if (!PeekNamedPipe (get_handle (), peek_buf, sizeof (peek_buf), &bytes_in_pipe, NULL, NULL)) if (!bytes_available (bytes_in_pipe))
{
termios_printf ("PeekNamedPipe failed, %E");
raise (SIGHUP); raise (SIGHUP);
bytes_in_pipe = 0;
}
/* On first peek determine no. of bytes to flush. */ /* On first peek determine no. of bytes to flush. */
if (!ptr && len == UINT_MAX) if (!ptr && len == UINT_MAX)
@ -826,12 +838,8 @@ fhandler_pty_slave::read (void *ptr, size_t& len)
number of bytes in pipe, but for some reason this number doesn't number of bytes in pipe, but for some reason this number doesn't
change after successful read. So we have to peek into the pipe change after successful read. So we have to peek into the pipe
again to see if input is still available */ again to see if input is still available */
if (!PeekNamedPipe (get_handle (), peek_buf, 1, &bytes_in_pipe, NULL, NULL)) if (!bytes_available (bytes_in_pipe))
{
termios_printf ("PeekNamedPipe failed, %E");
raise (SIGHUP); raise (SIGHUP);
bytes_in_pipe = 0;
}
if (n) if (n)
{ {
len -= n; len -= n;
@ -999,15 +1007,15 @@ fhandler_pty_slave::ioctl (unsigned int cmd, void *arg)
goto out; goto out;
case FIONREAD: case FIONREAD:
{ {
int n; DWORD n;
if (!PeekNamedPipe (get_handle (), NULL, 0, NULL, (DWORD *) &n, NULL)) if (!bytes_available (n))
{ {
set_errno (EINVAL); set_errno (EINVAL);
retval = -1; retval = -1;
} }
else else
{ {
*(int *) arg = n; *(int *) arg = (int) n;
retval = 0; retval = 0;
} }
} }
@ -1265,11 +1273,6 @@ fhandler_pty_master::cleanup ()
int int
fhandler_pty_master::close () fhandler_pty_master::close ()
{ {
#if 0
while (accept_input () > 0)
continue;
#endif
termios_printf ("closing from_master(%p)/to_master(%p) since we own them(%d)", termios_printf ("closing from_master(%p)/to_master(%p) since we own them(%d)",
from_master, to_master, dwProcessId); from_master, to_master, dwProcessId);
if (cygwin_finished_initializing) if (cygwin_finished_initializing)
@ -1420,13 +1423,13 @@ fhandler_pty_master::ioctl (unsigned int cmd, void *arg)
return this->tcsetpgrp ((pid_t) arg); return this->tcsetpgrp ((pid_t) arg);
case FIONREAD: case FIONREAD:
{ {
int n; DWORD n;
if (!PeekNamedPipe (to_master, NULL, 0, NULL, (DWORD *) &n, NULL)) if (!::bytes_available (n, to_master))
{ {
set_errno (EINVAL); set_errno (EINVAL);
return -1; return -1;
} }
*(int *) arg = n; *(int *) arg = (DWORD) n;
} }
break; break;
default: default:

View File

@ -552,11 +552,15 @@ peek_pipe (select_record *s, bool from_select)
switch (fh->get_major ()) switch (fh->get_major ())
{ {
case DEV_PTYM_MAJOR: case DEV_PTYM_MAJOR:
if (((fhandler_pty_master *) fh)->need_nl) {
fhandler_pty_master *fhm = (fhandler_pty_master *) fh;
fhm->flush_to_slave ();
if (fhm->need_nl)
{ {
gotone = s->read_ready = true; gotone = s->read_ready = true;
goto out; goto out;
} }
}
break; break;
default: default:
if (fh->get_readahead_valid ()) if (fh->get_readahead_valid ())