illumos,tty: UV_TTY_MODE_IO waits for 4 bytes

uv_tty_set_mode() allows a tty device to be set to raw mode with
UV_TTY_MODE_RAW, which correctly sets MIN and TIME to appropriate
values for character input. When UV_TTY_MODE_IO is passed, on illumos
systems a compatibility implementation of cfmakeraw() is used that does
_not_ set MIN or TIME. As a result, consumers of IO mode will block
until a minimum of 4 bytes is available on the tty instead of just 1 as
is expected.

PR-URL: https://github.com/libuv/libuv/pull/3219
Reviewed-By: Jameson Nash <vtjnash@gmail.com>
This commit is contained in:
Joshua M. Clulow 2021-07-02 12:06:18 -07:00 committed by GitHub
parent caf22ddbf5
commit b6d51dc40e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -242,6 +242,24 @@ static void uv__tty_make_raw(struct termios* tio) {
tio->c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); tio->c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
tio->c_cflag &= ~(CSIZE | PARENB); tio->c_cflag &= ~(CSIZE | PARENB);
tio->c_cflag |= CS8; tio->c_cflag |= CS8;
/*
* By default, most software expects a pending read to block until at
* least one byte becomes available. As per termio(7I), this requires
* setting the MIN and TIME parameters appropriately.
*
* As a somewhat unfortunate artifact of history, the MIN and TIME slots
* in the control character array overlap with the EOF and EOL slots used
* for canonical mode processing. Because the EOF character needs to be
* the ASCII EOT value (aka Control-D), it has the byte value 4. When
* switching to raw mode, this is interpreted as a MIN value of 4; i.e.,
* reads will block until at least four bytes have been input.
*
* Other platforms with a distinct MIN slot like Linux and FreeBSD appear
* to default to a MIN value of 1, so we'll force that value here:
*/
tio->c_cc[VMIN] = 1;
tio->c_cc[VTIME] = 0;
#else #else
cfmakeraw(tio); cfmakeraw(tio);
#endif /* #ifdef __sun */ #endif /* #ifdef __sun */