select() fails on multi-byte input in cygwin console (since 1.7.10)

Thomas Wolff
Tue Dec 9 07:02:00 GMT 2014

Calling select() to check whether input from the terminal is available
fails for all but the first byte in the cygwin console if multiple bytes
are entered at once, like function or cursor keys or non-ASCII UTF-8
Actually, the issue is volatile, sometimes it works for characters and
most function keys.
The problem most likely arises with the escape sequences mouse scroll
and window focus out/in (both enabled by the test program).
I tried to use read() with timeout instead, trying various combinations
of tcsetattr setting VMIN/VTIME, fcntl setting O_NONBLOCK, using read()
with buffer length 0, trying to interrupt read() with a timer signal, or
even a combination of setitimer() and siglongjmp().
None of this works.

Thanks to the cygwin time machine, I could track back this bug to have
appeared in 1.7.10 (around the time I had reported another select()
issue: which I
hope doesn’t interfere, nor the later issue


Diese E-Mail wurde von Avast Antivirus-Software auf Viren geprüft.
-------------- next part --------------
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <stdio.h>

#include <sys/select.h>
#include <time.h>
#include <signal.h>

struct termios saved_tattr;

restore_tattr (void)
  if (isatty (STDIN_FILENO))
    tcsetattr (STDIN_FILENO, TCSANOW, &saved_tattr);

ready_select ()
  struct timeval timeoutstru;
  fd_set readfds;
  int nfds;
  static int rv = 0;

  timeoutstru.tv_sec = 0;
  timeoutstru.tv_usec = 800000;

  FD_ZERO (& readfds);
  FD_SET (STDIN_FILENO, & readfds);
  nfds = select (STDIN_FILENO + 1, & readfds, 0, 0, & timeoutstru);
  printf ("(%d)", nfds);
  return nfds;

main (void)
  if (isatty (STDIN_FILENO)) {
    struct termios tattr;
    tcgetattr (STDIN_FILENO, &saved_tattr);
    tattr = saved_tattr;
    tattr.c_oflag &= ~OPOST;
    tattr.c_cflag &= ~(CSIZE|PARENB);
    tattr.c_cflag |= CS8;
    tattr.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
    /* use miminal change for test case: */
    tattr.c_lflag &= ~(ICANON);
    tcsetattr (STDIN_FILENO, TCSAFLUSH, &tattr);
    atexit (restore_tattr);
  setbuf (stdout, 0);

  printf ("\033[?1000h\033[?1006h\033[?1004h");
  while (1) {
    unsigned char c;
    int res;

    while (! ready_select ()) {

    res = read (STDIN_FILENO, & c, 1);
    switch (c & 0xFF) {
      case 0x00 ... 0x1f:  putchar ('^'); putchar (c + 0x40);
                           if (c == '\r') printf ("\r\n");
      case 0x7f: putchar ('^'); putchar ('?'); break;
      case 0x80 ... 0xFF: printf ("\\x%2X", c); break;
      default: putchar (c);
    fflush (stdout);
  printf ("\033[?1000l\033[?1004l\r\nbye\r\n");
  return 0;
-------------- next part --------------
Problem reports:
Unsubscribe info:

More information about the Cygwin mailing list