Cygwin: console: fix select() behaviour

- Previously, select() would return when only one key is typed even
  in canonical mode. With this patch, it returns after one line is
  completed.
This commit is contained in:
Takashi Yano 2019-04-01 00:47:47 +09:00 committed by Corinna Vinschen
parent bd627864ab
commit 8382778cdb
3 changed files with 484 additions and 447 deletions

View File

@ -1884,6 +1884,15 @@ public:
tty_min tty_min_state; tty_min tty_min_state;
dev_console con; dev_console con;
}; };
bool input_ready;
enum input_states
{
input_error = -1,
input_processing = 0,
input_ok = 1,
input_signalled = 2,
input_winch = 3
};
private: private:
static const unsigned MAX_WRITE_CHARS; static const unsigned MAX_WRITE_CHARS;
static console_state *shared_console_info; static console_state *shared_console_info;
@ -1969,7 +1978,7 @@ private:
void fixup_after_fork (HANDLE) {fixup_after_fork_exec (false);} void fixup_after_fork (HANDLE) {fixup_after_fork_exec (false);}
void set_close_on_exec (bool val); void set_close_on_exec (bool val);
void set_input_state (); void set_input_state ();
void send_winch_maybe (); bool send_winch_maybe ();
void setup (); void setup ();
bool set_unit (); bool set_unit ();
static bool need_invisible (); static bool need_invisible ();
@ -1992,6 +2001,7 @@ private:
copyto (fh); copyto (fh);
return fh; return fh;
} }
input_states process_input_message ();
friend tty_min * tty_list::get_cttyp (); friend tty_min * tty_list::get_cttyp ();
}; };

File diff suppressed because it is too large Load Diff

View File

@ -202,7 +202,9 @@ select (int maxfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
right value >= 0, matching the number of bits set in the right value >= 0, matching the number of bits set in the
fds records. if ret is 0, continue to loop. */ fds records. if ret is 0, continue to loop. */
ret = sel.poll (readfds, writefds, exceptfds); ret = sel.poll (readfds, writefds, exceptfds);
if (!ret) if (ret < 0)
wait_state = select_stuff::select_signalled;
else if (!ret)
wait_state = select_stuff::select_set_zero; wait_state = select_stuff::select_set_zero;
} }
/* Always clean up everything here. If we're looping then build it /* Always clean up everything here. If we're looping then build it
@ -479,6 +481,7 @@ was_timeout:
events like mouse movements. The verify function will detect these events like mouse movements. The verify function will detect these
situations. If it returns false, then this wakeup was a false alarm situations. If it returns false, then this wakeup was a false alarm
and we should go back to waiting. */ and we should go back to waiting. */
int ret = 0;
while ((s = s->next)) while ((s = s->next))
if (s->saw_error ()) if (s->saw_error ())
{ {
@ -488,8 +491,13 @@ was_timeout:
} }
else if ((((wait_ret >= m && s->windows_handle) else if ((((wait_ret >= m && s->windows_handle)
|| s->h == w4[wait_ret])) || s->h == w4[wait_ret]))
&& s->verify (s, readfds, writefds, exceptfds)) && (ret = s->verify (s, readfds, writefds, exceptfds)) > 0)
res = select_ok; res = select_ok;
else if (ret < 0)
{
res = select_signalled;
goto out;
}
select_printf ("res after verify %d", res); select_printf ("res after verify %d", res);
break; break;
@ -539,8 +547,12 @@ select_stuff::poll (fd_set *readfds, fd_set *writefds, fd_set *exceptfds)
int n = 0; int n = 0;
select_record *s = &start; select_record *s = &start;
while ((s = s->next)) while ((s = s->next))
n += (!s->peek || s->peek (s, true)) ? {
set_bits (s, readfds, writefds, exceptfds) : 0; int ret = s->peek ? s->peek (s, true) : 1;
if (ret < 0)
return -1;
n += (ret > 0) ? set_bits (s, readfds, writefds, exceptfds) : 0;
}
return n; return n;
} }
@ -1010,16 +1022,10 @@ peek_console (select_record *me, bool)
return me->write_ready; return me->write_ready;
if (fh->get_cons_readahead_valid ()) if (fh->get_cons_readahead_valid ())
{ return me->read_ready = true;
select_printf ("cons_readahead");
return me->read_ready = true;
}
if (fh->get_readahead_valid ()) if (fh->input_ready)
{ return me->read_ready = true;
select_printf ("readahead");
return me->read_ready = true;
}
if (me->read_ready) if (me->read_ready)
{ {
@ -1030,54 +1036,20 @@ peek_console (select_record *me, bool)
INPUT_RECORD irec; INPUT_RECORD irec;
DWORD events_read; DWORD events_read;
HANDLE h; HANDLE h;
char tmpbuf[17];
set_handle_or_return_if_not_open (h, me); set_handle_or_return_if_not_open (h, me);
for (;;) while (!fh->input_ready && !fh->get_cons_readahead_valid ())
if (fh->bg_check (SIGTTIN, true) <= bg_eof) if (fh->bg_check (SIGTTIN, true) <= bg_eof)
return me->read_ready = true; return me->read_ready = true;
else if (!PeekConsoleInputW (h, &irec, 1, &events_read) || !events_read) else if (!PeekConsoleInputW (h, &irec, 1, &events_read) || !events_read)
break; break;
else else if (fhandler_console::input_winch == fh->process_input_message ())
{ {
fh->send_winch_maybe (); set_sig_errno (EINTR);
if (irec.EventType == KEY_EVENT) return -1;
{
if (irec.Event.KeyEvent.bKeyDown)
{
/* Ignore Alt+Numpad keys. They are eventually handled in the
key-up case below. */
if (is_alt_numpad_key (&irec))
;
/* Handle normal input. */
else if (irec.Event.KeyEvent.uChar.UnicodeChar
|| fhandler_console::get_nonascii_key (irec, tmpbuf))
return me->read_ready = true;
/* Allow Ctrl-Space for ^@ */
else if ( (irec.Event.KeyEvent.wVirtualKeyCode == VK_SPACE
|| irec.Event.KeyEvent.wVirtualKeyCode == '2')
&& (irec.Event.KeyEvent.dwControlKeyState &
(LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED))
&& !(irec.Event.KeyEvent.dwControlKeyState
& (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)) )
return me->read_ready = true;
}
/* Ignore key up events, except for Alt+Numpad events. */
else if (is_alt_numpad_event (&irec))
return me->read_ready = true;
}
else
{
if (irec.EventType == MOUSE_EVENT
&& fh->mouse_aware (irec.Event.MouseEvent))
return me->read_ready = true;
if (irec.EventType == FOCUS_EVENT && fh->focus_aware ())
return me->read_ready = true;
}
/* Read and discard the event */
ReadConsoleInputW (h, &irec, 1, &events_read);
} }
if (fh->input_ready || fh->get_cons_readahead_valid ())
return me->read_ready = true;
return me->write_ready; return me->write_ready;
} }
@ -1089,7 +1061,6 @@ verify_console (select_record *me, fd_set *rfds, fd_set *wfds,
return peek_console (me, true); return peek_console (me, true);
} }
select_record * select_record *
fhandler_console::select_read (select_stuff *ss) fhandler_console::select_read (select_stuff *ss)
{ {
@ -1104,7 +1075,7 @@ fhandler_console::select_read (select_stuff *ss)
s->peek = peek_console; s->peek = peek_console;
s->h = get_handle (); s->h = get_handle ();
s->read_selected = true; s->read_selected = true;
s->read_ready = get_readahead_valid (); s->read_ready = input_ready || get_cons_readahead_valid ();
return s; return s;
} }