Index: fhandler.h =================================================================== RCS file: /cvs/src/src/winsup/cygwin/fhandler.h,v retrieving revision 1.41 diff -u -p -2 -r1.41 fhandler.h --- fhandler.h 2001/02/27 09:14:35 1.41 +++ fhandler.h 2001/02/28 14:10:42 @@ -707,5 +707,6 @@ public: 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 Index: fhandler_tty.cc =================================================================== RCS file: /cvs/src/src/winsup/cygwin/fhandler_tty.cc,v retrieving revision 1.23 diff -u -p -2 -r1.23 fhandler_tty.cc --- fhandler_tty.cc 2000/10/17 01:42:04 1.23 +++ fhandler_tty.cc 2001/02/28 14:10:44 @@ -168,20 +168,19 @@ 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; } @@ -460,4 +459,17 @@ fhandler_tty_slave::open (const char *, 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, @@ -600,5 +612,10 @@ fhandler_tty_slave::read (void *ptr, siz 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 ()); @@ -606,21 +623,77 @@ fhandler_tty_slave::read (void *ptr, siz 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 @@ -635,46 +708,26 @@ fhandler_tty_slave::read (void *ptr, siz 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); @@ -722,9 +775,23 @@ fhandler_tty_common::dup (fhandler_base 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; } @@ -733,5 +800,5 @@ fhandler_tty_common::dup (fhandler_base DUPLICATE_SAME_ACCESS)) { - errind = 5; + errind = 7; goto err; } @@ -742,5 +809,5 @@ fhandler_tty_common::dup (fhandler_base DUPLICATE_SAME_ACCESS)) { - errind = 6; + errind = 8; goto err; } @@ -753,5 +820,5 @@ fhandler_tty_common::dup (fhandler_base DUPLICATE_SAME_ACCESS)) { - errind = 7; + errind = 9; goto err; } @@ -889,4 +956,8 @@ fhandler_tty_common::close () 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 ()); @@ -1010,4 +1081,6 @@ fhandler_tty_common::set_close_on_exec ( 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); } @@ -1028,4 +1101,11 @@ fhandler_tty_common::fixup_after_fork (H 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"); Index: tty.cc =================================================================== RCS file: /cvs/src/src/winsup/cygwin/tty.cc,v retrieving revision 1.13 diff -u -p -2 -r1.13 tty.cc --- tty.cc 2000/10/17 01:42:04 1.13 +++ tty.cc 2001/02/28 14:10:44 @@ -409,4 +409,7 @@ tty::common_init (fhandler_pty_master *p } + if (!(ptym->input_available_event = get_event (INPUT_AVAILABLE_EVENT, FALSE))) + return FALSE; + char buf[40]; __small_sprintf (buf, OUTPUT_MUTEX, ntty); @@ -418,5 +421,14 @@ tty::common_init (fhandler_pty_master *p } + __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; Index: tty.h =================================================================== RCS file: /cvs/src/src/winsup/cygwin/tty.h,v retrieving revision 1.2 diff -u -p -2 -r1.2 tty.h --- tty.h 2000/10/27 15:38:32 1.2 +++ tty.h 2001/02/28 14:10:44 @@ -24,5 +24,7 @@ details. */ #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" @@ -110,4 +112,10 @@ public: char buf[80]; __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); }