summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--winsup/cygwin/ChangeLog19
-rw-r--r--winsup/cygwin/fhandler.h3
-rw-r--r--winsup/cygwin/fhandler_tty.cc214
-rw-r--r--winsup/cygwin/tty.cc12
-rw-r--r--winsup/cygwin/tty.h8
5 files changed, 188 insertions, 68 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 3e6b8b351..35b7fa5df 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,22 @@
+2001-03-04 Egor Duda <deo@logos-m.ru>
+
+ * fhandler.h (class fhandler_tty_common): New mutex and event to
+ syncronize input on master tty with slave tty.
+ * fhandler_tty.cc (fhandler_pty_master::accept_input): Use them to
+ syncronize with slave.
+ * fhandler_tty.cc (fhandler_tty_slave::read): Use input mutex and
+ event to syncronize with master. Do not limit amount of data read
+ from master to vmin value. Interrupt on signal and return already
+ read data, if any.
+ * fhandler_tty.cc (fhandler_tty_slave::open): Handle input mutex and
+ event.
+ * fhandler_tty.cc (fhandler_tty_common::close): Ditto.
+ * fhandler_tty.cc (fhandler_tty_common::set_close_on_exec): Ditto.
+ * fhandler_tty.cc (fhandler_tty_common::fixup_after_fork): Ditto.
+ * fhandler_tty.cc (fhandler_tty_common::dup): Ditto.
+ * tty.h (tty::open_input_mutex): New function.
+ * tty.cc (tty::common_init): Create input mutex and event.
+
Fri Mar 2 13:32:00 2001 Corinna Vinschen <corinna@vinschen.de>
* dir.cc (readdir): Fix creating path in symlink check.
diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index 3607b3b28..73aa294a6 100644
--- a/winsup/cygwin/fhandler.h
+++ b/winsup/cygwin/fhandler.h
@@ -707,7 +707,8 @@ public:
// Ioctl() request in tty::cmd/arg.
HANDLE ioctl_done_event; // Raised by master on ioctl() completion.
// Ioctl() status in tty::ioctl_retval.
- HANDLE output_mutex;
+ HANDLE output_mutex, input_mutex;
+ HANDLE input_available_event;
HANDLE inuse; // used to indicate that a tty is in use
diff --git a/winsup/cygwin/fhandler_tty.cc b/winsup/cygwin/fhandler_tty.cc
index 01a5a9691..c3165285e 100644
--- a/winsup/cygwin/fhandler_tty.cc
+++ b/winsup/cygwin/fhandler_tty.cc
@@ -167,22 +167,21 @@ fhandler_pty_master::accept_input ()
{
DWORD written;
DWORD n;
- const char dummy[1] = {'X'};
- const char *buf;
+ DWORD rc;
+
+ rc = WaitForSingleObject (input_mutex, INFINITE);
n = get_ttyp ()->read_retval = eat_readahead (-1);
- if (n != 0)
- buf = rabuf;
- else
+ if ( n != 0 )
{
- n = 1;
- buf = dummy;
- termios_printf ("sending EOF to slave");
+ termios_printf ("about to write %d chars to slave", n);
+ rc = WriteFile (get_output_handle (), rabuf, n, &written, NULL);
}
- termios_printf ("about to write %d chars to slave", n);
- if (!WriteFile (get_output_handle (), buf, n, &written, NULL))
- return -1;
+ else
+ termios_printf ("sending EOF to slave");
+ SetEvent (input_available_event);
+ ReleaseMutex (input_mutex);
return get_ttyp ()->read_retval;
}
@@ -459,6 +458,19 @@ fhandler_tty_slave::open (const char *, int flags, mode_t)
__seterrno ();
return 0;
}
+ if (!(input_mutex = get_ttyp()->open_input_mutex (TRUE)))
+ {
+ termios_printf ("open input mutex failed, %E");
+ __seterrno ();
+ return 0;
+ }
+ __small_sprintf (buf, INPUT_AVAILABLE_EVENT, ttynum);
+ if (!(input_available_event = OpenEvent (EVENT_ALL_ACCESS, TRUE, buf)))
+ {
+ termios_printf ("open input event failed, %E");
+ __seterrno ();
+ return 0;
+ }
/* The ioctl events may or may not exist. See output_done_event,
above. */
@@ -599,29 +611,90 @@ fhandler_tty_slave::read (void *ptr, size_t len)
int totalread = 0;
int vmin = INT_MAX;
int vtime = 0; /* Initialized to prevent -Wuninitialized warning */
+ size_t readlen;
+ DWORD bytes_in_pipe;
char buf[INP_BUFFER_SIZE];
+ DWORD time_to_wait;
+ DWORD rc;
+ HANDLE w4[2];
- termios_printf("read(%x, %d) handle %d", ptr, len, get_handle ());
+ termios_printf ("read(%x, %d) handle %d", ptr, len, get_handle ());
if (!(get_ttyp ()->ti.c_lflag & ICANON))
{
- vmin = get_ttyp ()->ti.c_cc[VMIN];
+ vmin = min (INP_BUFFER_SIZE, get_ttyp ()->ti.c_cc[VMIN]);
vtime = get_ttyp ()->ti.c_cc[VTIME];
+ if (vmin < 0) vmin = 0;
+ if (vtime < 0) vtime = 0;
+ if (vmin == 0)
+ time_to_wait = INFINITE;
+ else
+ time_to_wait = (vtime == 0 ? INFINITE : 10 * vtime);
}
+ else
+ time_to_wait = INFINITE;
+
+ w4[0] = signal_arrived;
+ w4[1] = input_available_event;
while (len)
{
- size_t readlen = min ((unsigned) vmin, min (len, sizeof (buf)));
- termios_printf ("reading %d bytes (vtime %d)",
- min ((unsigned) vmin, min (len, sizeof (buf))), vtime);
-
- n = get_readahead_into_buffer (buf, readlen);
-
- if (!n && ReadFile (get_handle (), buf, readlen, &n, NULL) == FALSE)
+ rc = WaitForMultipleObjects (2, w4, FALSE, time_to_wait);
+ if (rc == WAIT_OBJECT_0)
+ {
+ /* if we've recieved signal after successfully reading some data,
+ just return all data successfully read */
+ if (totalread > 0)
+ break;
+ set_sig_errno (EINTR);
+ return -1;
+ }
+ else if (rc == WAIT_FAILED)
+ {
+ termios_printf ("wait for input event failed, %E");
+ break;
+ }
+ else if (rc == WAIT_TIMEOUT)
+ break;
+ rc = WaitForSingleObject (input_mutex, 1000);
+ if (rc == WAIT_FAILED)
+ {
+ termios_printf ("wait for input mutex failed, %E");
+ break;
+ }
+ else if (rc == WAIT_TIMEOUT)
+ {
+ termios_printf ("failed to acquire input mutex after input event arrived");
+ break;
+ }
+ if (!PeekNamedPipe (get_handle (), NULL, 0, NULL, &bytes_in_pipe, NULL))
{
- termios_printf ("read failed, %E");
- _raise (SIGHUP);
+ termios_printf ("PeekNamedPipe failed, %E");
+ _raise (SIGHUP);
+ bytes_in_pipe = 0;
}
+ readlen = min (bytes_in_pipe, min (len, sizeof (buf)));
+ if ( readlen )
+ {
+ termios_printf ("reading %d bytes (vtime %d)", readlen, vtime);
+ if (ReadFile (get_handle (), buf, readlen, &n, NULL) == FALSE)
+ {
+ termios_printf ("read failed, %E");
+ _raise (SIGHUP);
+ }
+ if (n)
+ {
+ len -= n;
+ totalread += n;
+ memcpy (ptr, buf, n);
+ ptr = (char *) ptr + n;
+ }
+ }
+
+ if (readlen != bytes_in_pipe)
+ SetEvent (input_available_event);
+
+ ReleaseMutex (input_mutex);
if (get_ttyp ()->read_retval < 0) // read error
{
@@ -634,48 +707,28 @@ fhandler_tty_slave::read (void *ptr, size_t len)
termios_printf ("saw EOF");
break;
}
- len -= n;
- totalread += n;
- memcpy (ptr, buf, n);
- ptr = (char *) ptr + n;
- if (get_ttyp ()->ti.c_lflag & ICANON)
- break;
- else if (totalread >= vmin)
+ if ( get_ttyp ()->ti.c_lflag & ICANON ||
+ get_flags () & (O_NONBLOCK | O_NDELAY))
break;
-
- if (!PeekNamedPipe (get_handle (), NULL, 0, NULL, &n, NULL))
- {
- termios_printf("PeekNamedPipe failed, %E");
- break;
- }
- if (n == 0)
- {
- if (get_flags () & (O_NONBLOCK | O_NDELAY))
- break;
-
- /* We can't enter the blocking Readfile as signals will be lost.
- * So, poll the pipe for data.
- * FIXME: try to avoid polling...
- * FIXME: Current EINTR scheme does not take vmin/vtime into account.
- */
- if (!(get_ttyp ()->ti.c_lflag & ICANON))
- {
- termios_printf("vmin %d vtime %d", vmin, vtime);
- if (vmin == 0 && vtime == 0)
- return 0; // min = 0, time = 0
- if (vtime == 0)
- continue; // min > 0, time = 0
- while (vtime--)
- {
- PeekNamedPipe (get_handle (), NULL, 0, NULL, &n, NULL);
- if (n)
- break;
- Sleep(10);
- }
- if (vtime == 0)
- return totalread;
- }
- }
+ if (totalread >= vmin && (vmin > 0 || totalread > 0))
+ break;
+
+ /* vmin == 0 && vtime == 0:
+ * we've already read all input, if any, so return immediately
+ * vmin == 0 && vtime > 0:
+ * we've waited for input 10*vtime ms in WFSO(input_available_event),
+ * no matter whether any input arrived, we shouldn't wait any longer,
+ * so return immediately
+ * vmin > 0 && vtime == 0:
+ * here, totalread < vmin, so continue waiting until more data
+ * arrive
+ * vmin > 0 && vtime > 0:
+ * similar to the previous here, totalread < vmin, and timer
+ * hadn't expired -- WFSO(input_available_event) != WAIT_TIMEOUT,
+ * so "restart timer" and wait until more data arrive
+ */
+
+ if (vmin == 0) break;
}
termios_printf ("%d=read(%x, %d)", totalread, ptr, len);
return totalread;
@@ -721,18 +774,32 @@ fhandler_tty_common::dup (fhandler_base *child)
errind = 3;
goto err;
}
+ if (!DuplicateHandle (hMainProc, input_available_event, hMainProc,
+ &fts->input_available_event, 0, 1,
+ DUPLICATE_SAME_ACCESS))
+ {
+ errind = 4;
+ goto err;
+ }
if (!DuplicateHandle (hMainProc, output_mutex, hMainProc,
&fts->output_mutex, 0, 1,
DUPLICATE_SAME_ACCESS))
{
- errind = 4;
+ errind = 5;
+ goto err;
+ }
+ if (!DuplicateHandle (hMainProc, input_mutex, hMainProc,
+ &fts->input_mutex, 0, 1,
+ DUPLICATE_SAME_ACCESS))
+ {
+ errind = 6;
goto err;
}
if (!DuplicateHandle (hMainProc, get_handle (), hMainProc,
&nh, 0, 1,
DUPLICATE_SAME_ACCESS))
{
- errind = 5;
+ errind = 7;
goto err;
}
fts->set_io_handle (nh);
@@ -741,7 +808,7 @@ fhandler_tty_common::dup (fhandler_base *child)
&nh, 0, 1,
DUPLICATE_SAME_ACCESS))
{
- errind = 6;
+ errind = 8;
goto err;
}
fts->set_output_handle (nh);
@@ -752,7 +819,7 @@ fhandler_tty_common::dup (fhandler_base *child)
&fts->inuse, 0, 1,
DUPLICATE_SAME_ACCESS))
{
- errind = 7;
+ errind = 9;
goto err;
}
return 0;
@@ -888,6 +955,10 @@ fhandler_tty_common::close ()
termios_printf ("CloseHandle (inuse), %E");
if (!ForceCloseHandle (output_mutex))
termios_printf ("CloseHandle (output_mutex<%p>), %E", output_mutex);
+ if (!ForceCloseHandle (input_mutex))
+ termios_printf ("CloseHandle (input_mutex<%p>), %E", input_mutex);
+ if (!ForceCloseHandle (input_available_event))
+ termios_printf ("CloseHandle (input_available_event<%p>), %E", input_available_event);
if (!ForceCloseHandle1 (get_handle (), from_pty))
termios_printf ("CloseHandle (get_handle ()<%p>), %E", get_handle ());
if (!ForceCloseHandle1 (get_output_handle (), to_pty))
@@ -1009,6 +1080,8 @@ fhandler_tty_common::set_close_on_exec (int val)
if (inuse)
set_inheritance (inuse, val);
set_inheritance (output_mutex, val, "output_mutex");
+ set_inheritance (input_mutex, val, "input_mutex");
+ set_inheritance (input_available_event, val);
set_inheritance (output_handle, val);
}
@@ -1027,6 +1100,13 @@ fhandler_tty_common::fixup_after_fork (HANDLE parent)
fork_fixup (parent, output_mutex, "output_mutex");
ProtectHandle (output_mutex);
}
+ if (input_mutex)
+ {
+ fork_fixup (parent, input_mutex, "input_mutex");
+ ProtectHandle (input_mutex);
+ }
+ if (input_available_event)
+ fork_fixup (parent, input_available_event, "input_available_event");
fork_fixup (parent, output_handle, "output_handle");
fork_fixup (parent, inuse, "inuse");
}
diff --git a/winsup/cygwin/tty.cc b/winsup/cygwin/tty.cc
index baff0a4c2..070fa3e28 100644
--- a/winsup/cygwin/tty.cc
+++ b/winsup/cygwin/tty.cc
@@ -408,6 +408,9 @@ tty::common_init (fhandler_pty_master *ptym)
return FALSE;
}
+ if (!(ptym->input_available_event = get_event (INPUT_AVAILABLE_EVENT, FALSE)))
+ return FALSE;
+
char buf[40];
__small_sprintf (buf, OUTPUT_MUTEX, ntty);
if (!(ptym->output_mutex = CreateMutex (&sec_all, FALSE, buf)))
@@ -417,7 +420,16 @@ tty::common_init (fhandler_pty_master *ptym)
return FALSE;
}
+ __small_sprintf (buf, INPUT_MUTEX, ntty);
+ if (!(ptym->input_mutex = CreateMutex (&sec_all, FALSE, buf)))
+ {
+ termios_printf ("can't create %s", buf);
+ set_errno (ENOENT);
+ return FALSE;
+ }
+
ProtectHandle1 (ptym->output_mutex, output_mutex);
+ ProtectHandle1 (ptym->input_mutex, input_mutex);
winsize.ws_col = 80;
winsize.ws_row = 25;
diff --git a/winsup/cygwin/tty.h b/winsup/cygwin/tty.h
index bdd6eaedf..36f7ae19d 100644
--- a/winsup/cygwin/tty.h
+++ b/winsup/cygwin/tty.h
@@ -23,7 +23,9 @@ details. */
#define IOCTL_REQUEST_EVENT "cygtty%d.ioctl.request"
#define IOCTL_DONE_EVENT "cygtty%d.ioctl.done"
#define RESTART_OUTPUT_EVENT "cygtty%d.output.restart"
+#define INPUT_AVAILABLE_EVENT "cygtty%d.input.avail"
#define OUTPUT_MUTEX "cygtty%d.output.mutex"
+#define INPUT_MUTEX "cygtty%d.input.mutex"
#define TTY_SLAVE_ALIVE "cygtty%x.slave_alive"
#define TTY_MASTER_ALIVE "cygtty%x.master_alive"
@@ -111,6 +113,12 @@ public:
__small_sprintf (buf, OUTPUT_MUTEX, ntty);
return OpenMutex (MUTEX_ALL_ACCESS, inherit, buf);
}
+ HANDLE open_input_mutex (BOOL inherit = FALSE)
+ {
+ char buf[80];
+ __small_sprintf (buf, INPUT_MUTEX, ntty);
+ return OpenMutex (MUTEX_ALL_ACCESS, inherit, buf);
+ }
BOOL exists ()
{
HANDLE h = open_output_mutex ();