Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEgor Duda <deo@logos-m.ru>2001-03-04 18:34:25 +0300
committerEgor Duda <deo@logos-m.ru>2001-03-04 18:34:25 +0300
commit306c4b6737136c7bb45228c284502eb643ec95ac (patch)
tree88b3eeaefe560eb41d42081a5648a15a40ec6eea /winsup/cygwin/fhandler_tty.cc
parent0312ede431278fb8a0aa6db9ae201d928d3b0055 (diff)
* 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.
Diffstat (limited to 'winsup/cygwin/fhandler_tty.cc')
-rw-r--r--winsup/cygwin/fhandler_tty.cc214
1 files changed, 147 insertions, 67 deletions
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");
}