* 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.
This commit is contained in:
Egor Duda 2001-03-04 15:34:25 +00:00
parent 0312ede431
commit 306c4b6737
5 changed files with 186 additions and 66 deletions

View File

@ -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.

View File

@ -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

View File

@ -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 (totalread >= vmin && (vmin > 0 || totalread > 0))
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;
/* 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
*/
/* 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 (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");
}

View File

@ -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;

View File

@ -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 ();