select() on terminal

The following program demonstrates what appears to
be a bug in the implementation of select() (or the
select handler) within the terminal driver(s).
I have tested this both in a pterm window and without
photon on 6.2.0.

The program is supposed to read a character at a time
from STDIN_FILENO while using select with a timeout
value. (There is probably a better way to do this,
but the code is taken from someone else’s software
(sudo) and appears to be legal.)

When you execute the program, it displays a prompt.

If you take no action for 5 seconds, it times out,
which is good.

If you type a single character other than ‘Enter’,
then wait, it will not timeout, which is bad.

If you type a few characters followed by ‘Enter’,
it will read one character, then block. select()
is apparently not returning even though there are
more characters available for reading. If you hit
‘Enter’ again, all of the characters are read -
select() has now recognizes that there are more
characters available. [This behaviour is independent
of the use of a timeout value.]

[Because the console is in edited mode, it is
reasonable to expect select() to wait until the
newline is entered before returning.]

-Norton Allen

#include <stdio.h>
#include <unistd.h>
#include <sys/uio.h>
#include <sys/time.h>
#include <stdlib.h>
#include <errno.h>

int main( int argc, char **argv ) {
int c, n;
fd_set *readfds = NULL;
struct timeval tv;
int fd = STDIN_FILENO;
int timeout = 5;

printf( "Enter Text: " );
fflush(stdout);

readfds = (fd_set *) malloc(sizeof(fd_set));
FD_ZERO(readfds);


for (;:wink: {
FD_SET(fd, readfds);

/* Set timeout for select /
tv.tv_sec = timeout;
tv.tv_usec = 0;
/
Make sure there is something to read (or timeout) /
while ((n = select(fd + 1, readfds, 0, 0, &tv)) == -1 &&
errno == EAGAIN) {
tv.tv_sec = timeout;
tv.tv_usec = 0;
}
if (n <= 0) {
free(readfds);
printf( “select returned %d (timeout or interrupt)\n”, n );
return(0); /
timeout or interrupt */
}
n = read( fd, &c, 1 );
if ( n != 1 || c == ‘\n’ || c == ‘\r’ )
break;
printf(“read c=%d\n”, c );
}
free(readfds);
if ( n != 1 ) printf(“read n=%d\n”, n );
else printf(“read c=%d\n”, c );
return 0;
}

Norton Allen <allen@huarp.harvard.edu> wrote:

The following program demonstrates what appears to
be a bug in the implementation of select() (or the
select handler) within the terminal driver(s).
I have tested this both in a pterm window and without
photon on 6.2.0.

It is documented at the end of the help page on select(). You can only call
select() on terminals in RAW mode.

chris


Chris McKillop <cdm@qnx.com> “The faster I go, the behinder I get.”
Software Engineer, QSSL – Lewis Carroll –
http://qnx.wox.org/

Norton Allen <allen@huarp.harvard.edu> wrote:

[Because the console is in edited mode, it is
reasonable to expect select() to wait until the
newline is entered before returning.]

From the select() docs:

Caveats:
The select() function only works with raw file descriptors; it doesn’t
work with file descriptors in edited mode. See the ICANON flag in
the description of the tcgetattr() function.

-David

QNX Training Services
http://www.qnx.com/support/training/
Please followup in this newsgroup if you have further questions.

David Gibbs wrote:

Norton Allen <> allen@huarp.harvard.edu> > wrote:


[Because the console is in edited mode, it is
reasonable to expect select() to wait until the
newline is entered before returning.]


From the select() docs:

Caveats:
The select() function only works with raw file descriptors; it doesn’t
work with file descriptors in edited mode. See the ICANON flag in
the description of the tcgetattr() function.

-David

Thanks, I obviously missed that. It’s nice that it’s
documented. Do you consider this to be a non-standard
limitation, or is this a common limitation of select
with terminals on other operating systems?

A related question: is there any particular reason
why it couldn’t be made to work? (not counting time
and money) (This may be an academic question, but
heck, I work at Harvard!)

I ask because this code is used within the sudo
package, which clearly expects select() to work
on a file descriptor in editted mode, and I’m wondering
what I should say to the maintainer.

-Norton

Norton Allen <allen@huarp.harvard.edu> wrote in message
news:b9g8oq$sd0$1@inn.qnx.com

David Gibbs wrote:
From the select() docs:

Caveats:
The select() function only works with raw file descriptors; it doesn’t
work with file descriptors in edited mode. See the ICANON flag in
the description of the tcgetattr() function.

-David

Thanks, I obviously missed that. It’s nice that it’s
documented. Do you consider this to be a non-standard
limitation, or is this a common limitation of select
with terminals on other operating systems?

A related question: is there any particular reason
why it couldn’t be made to work? (not counting time
and money) (This may be an academic question, but
heck, I work at Harvard!)

I ask because this code is used within the sudo
package, which clearly expects select() to work
on a file descriptor in editted mode, and I’m wondering
what I should say to the maintainer.

Hm… Say we are in EDIT mode.

The user type “A”, your select() return, you read out the
character.

The user then press , what is the terminal
suppose to do? It want to earse the “A”, but the character
is no longer there!

-xtang

Xiaodan Tang wrote:

Norton Allen <> allen@huarp.harvard.edu> > wrote in message
news:b9g8oq$sd0$> 1@inn.qnx.com> …

David Gibbs wrote:

From the select() docs:

Caveats:
The select() function only works with raw file descriptors; it doesn’t
work with file descriptors in edited mode. See the ICANON flag in
the description of the tcgetattr() function.

-David

Thanks, I obviously missed that. It’s nice that it’s
documented. Do you consider this to be a non-standard
limitation, or is this a common limitation of select
with terminals on other operating systems?

A related question: is there any particular reason
why it couldn’t be made to work? (not counting time
and money) (This may be an academic question, but
heck, I work at Harvard!)

I ask because this code is used within the sudo
package, which clearly expects select() to work
on a file descriptor in editted mode, and I’m wondering
what I should say to the maintainer.


Hm… Say we are in EDIT mode.

The user type “A”, your select() return, you read out the
character.

I would consider that incorrect behaviour for select()
(see below).

The user then press , what is the terminal
suppose to do? It want to earse the “A”, but the character
is no longer there!

-xtang

Since you’re in edit mode, it is entirely reasonable
to assume that select would not indicate that characters
are available for reading until you hit ‘Enter’. But once
you have hit ‘Enter’, you would expect select() to report
that there are characters to read until you have read up
to that newline character. This seems logically self-
consistent to me. Am I missing something.

I agree (assuming you mean through the newline, of course).

dB

“Norton Allen” <allen@huarp.harvard.edu> wrote in message
news:b9ga7p$17m$1@inn.qnx.com

Since you’re in edit mode, it is entirely reasonable
to assume that select would not indicate that characters
are available for reading until you hit ‘Enter’. But once
you have hit ‘Enter’, you would expect select() to report
that there are characters to read until you have read up
to that newline character. This seems logically self-
consistent to me. Am I missing something.

David Bacon wrote:

I agree (assuming you mean through the newline, of course).

Of course! -N

dB

“Norton Allen” <> allen@huarp.harvard.edu> > wrote in message
news:b9ga7p$17m$> 1@inn.qnx.com> …
snip

Since you’re in edit mode, it is entirely reasonable
to assume that select would not indicate that characters
are available for reading until you hit ‘Enter’. But once
you have hit ‘Enter’, you would expect select() to report
that there are characters to read until you have read up
to that newline character. This seems logically self-
consistent to me. Am I missing something.
\