2001-07-25 12:17:46

by M. Tavasti

[permalink] [raw]
Subject: Select with device and stdin not working


I found this problem first time in 2.2 kernels, when doing own device
driver. Then it was not an issue for me, and I suspected it's my
fault. Now, with 2.4 again I tried to solve problem, but I can't find
my way out of this, and looks like there in-kernel drivers which have
same symptoms.

Here program where I get problems:

int fd;
fd_set rfds;

fd = open("/dev/random", O_RDWR );

while(1) {
FD_ZERO(&rfds);
FD_SET(fd,&rfds);
FD_SET(fileno(stdin),&rfds);
if( select(fd+1, &rfds, NULL, NULL, NULL ) > 0) {
fprintf(stderr,"Select\n");
fflush(stderr);
if(FD_ISSET(fd,&rfds)) {
.......
} else if(FD_ISSET(fileno(stdin),&rfds) ) {
......
}
}
}


Select is working fine for device (in this example /dev/random) or
stdin. But for both, not. When entering something to stdin, it's not
sure select will return.

I haven't tested is this problem present in all devices, but at least
/dev/random is infected. And if problem lies only in some of the
drivers, it would be nice to know which driver haves decent
implementation of poll and get others updated.

I'm not subsribed on the list, so when replying this you may consider
Cc:ing me.

--
M. Tavasti / [email protected] / +358-40-5078254


2001-07-25 13:15:09

by Ketil Froyn

[permalink] [raw]
Subject: Re: Select with device and stdin not working

On 25 Jul 2001, M. Tavasti wrote:

> Here program where I get problems:
>
> int fd;
> fd_set rfds;
>
> fd = open("/dev/random", O_RDWR );
>
> while(1) {
> FD_ZERO(&rfds);
> FD_SET(fd,&rfds);
> FD_SET(fileno(stdin),&rfds);
> if( select(fd+1, &rfds, NULL, NULL, NULL ) > 0) {
> fprintf(stderr,"Select\n");
> fflush(stderr);
> if(FD_ISSET(fd,&rfds)) {
> .......
> } else if(FD_ISSET(fileno(stdin),&rfds) ) {
> ......
> }
> }
> }

It looks like you are sending the original fd_set to select. Remember that
it is modified in place. What is probably happening is that select returns
at once when it gets something from /dev/random, and rfds is now modified
to only contain this. The next time select runs, it will only be checking
for input from /dev/random. You have to make a copy of rfds that is set
every time, and send that instead.

Ketil

2001-07-25 13:35:31

by M. Tavasti

[permalink] [raw]
Subject: Re: Select with device and stdin not working

Ketil Froyn <[email protected]> writes:

> > while(1) {
> > FD_ZERO(&rfds);
> > FD_SET(fd,&rfds);
> > FD_SET(fileno(stdin),&rfds);
> > if( select(fd+1, &rfds, NULL, NULL, NULL ) > 0) {
(Lines removed)
> > }
>
> It looks like you are sending the original fd_set to select. Remember that
> it is modified in place.

But one would at least expect FD_ZERO() to really clean up rfds, and
after it FD_SET() is used again, for every call of select(). And this
code works fine in 2.0 kernels, and also with 2.2 and 2.4 if I'm using
named pipe and stdin. Therefore I have strong belief problem is not
usage of select() but something else.

--
M. Tavasti / [email protected] / +358-40-5078254

2001-07-25 14:14:51

by Stephen Landamore

[permalink] [raw]
Subject: Re: Select with device and stdin not working

> Select is working fine for device (in this example /dev/random) or
> stdin. But for both, not. When entering something to stdin, it's not
> sure select will return.

If stdin is a tty, chances are select will not show any data ready
until you hit return - this is canonical mode (or cooked mode). Try
clearing canonical mode (or setting cbreak / raw mode).

In the case of stdin being a tty, and you are typing away, note that
your keypresses will generate entropy - so /dev/random probably will
become ready to read before stdin ;)

cheers,
stephen

--
Stephen Landamore, <[email protected]> Zeus Technology
Tel: +44 1223 525000 Universally Serving the Net
Fax: +44 1223 525100 http://www.zeus.com
Zeus Technology, Zeus House, Cowley Road, Cambridge, CB4 0ZT, ENGLAND

2001-07-25 14:16:11

by Ketil Froyn

[permalink] [raw]
Subject: Re: Select with device and stdin not working

On 25 Jul 2001, M. Tavasti wrote:

> But one would at least expect FD_ZERO() to really clean up rfds, and
> after it FD_SET() is used again, for every call of select(). And this
> code works fine in 2.0 kernels, and also with 2.2 and 2.4 if I'm using
> named pipe and stdin. Therefore I have strong belief problem is not
> usage of select() but something else.

Sorry, my bad. I misread your code.

Ketil


2001-07-25 15:07:39

by Richard B. Johnson

[permalink] [raw]
Subject: Re: Select with device and stdin not working

On Wed, 25 Jul 2001, Ben Greear wrote:

> "M. Tavasti" wrote:
> >
> > I found this problem first time in 2.2 kernels, when doing own device
> > driver. Then it was not an issue for me, and I suspected it's my
> > fault. Now, with 2.4 again I tried to solve problem, but I can't find
> > my way out of this, and looks like there in-kernel drivers which have
> > same symptoms.
> >
> > Here program where I get problems:
> >
> > int fd;
> > fd_set rfds;
> >
> > fd = open("/dev/random", O_RDWR );
> >
> > while(1) {
> > FD_ZERO(&rfds);
> > FD_SET(fd,&rfds);
> > FD_SET(fileno(stdin),&rfds);
> > if( select(fd+1, &rfds, NULL, NULL, NULL ) > 0) {
> > fprintf(stderr,"Select\n");
> > fflush(stderr);
> > if(FD_ISSET(fd,&rfds)) {
> > .......
> > } else if(FD_ISSET(fileno(stdin),&rfds) ) {
> > ......
> > }
> > }
> > }


Change:
} else if(FD_ISSET(fileno(stdin),&rfds) ) {
To:
} if(FD_ISSET(fileno(stdin),&rfds) ) {

Both of these bits can be (probably are) set.


Cheers,
Dick Johnson

Penguin : Linux version 2.4.1 on an i686 machine (799.53 BogoMips).

I was going to compile a list of innovations that could be
attributed to Microsoft. Once I realized that Ctrl-Alt-Del
was handled in the BIOS, I found that there aren't any.


2001-07-25 15:02:28

by Ben Greear

[permalink] [raw]
Subject: Re: Select with device and stdin not working

"M. Tavasti" wrote:
>
> I found this problem first time in 2.2 kernels, when doing own device
> driver. Then it was not an issue for me, and I suspected it's my
> fault. Now, with 2.4 again I tried to solve problem, but I can't find
> my way out of this, and looks like there in-kernel drivers which have
> same symptoms.
>
> Here program where I get problems:
>
> int fd;
> fd_set rfds;
>
> fd = open("/dev/random", O_RDWR );
>
> while(1) {
> FD_ZERO(&rfds);
> FD_SET(fd,&rfds);
> FD_SET(fileno(stdin),&rfds);
> if( select(fd+1, &rfds, NULL, NULL, NULL ) > 0) {
> fprintf(stderr,"Select\n");
> fflush(stderr);
> if(FD_ISSET(fd,&rfds)) {
> .......
> } else if(FD_ISSET(fileno(stdin),&rfds) ) {
> ......
> }
> }
> }
>
> Select is working fine for device (in this example /dev/random) or
> stdin. But for both, not. When entering something to stdin, it's not
> sure select will return.
>
> I haven't tested is this problem present in all devices, but at least
> /dev/random is infected. And if problem lies only in some of the
> drivers, it would be nice to know which driver haves decent
> implementation of poll and get others updated.

I also saw what I believe is a problem with select, but I haven't had
time to poke around the kernel to try to understand it. In my case,
the problem is that when I have raw sockets reading ethernet frames,
select will not return immediately when there is a packet ready. When
it does return, due to timeout, or another FD in the set being ready
for action, the FD is set correctly though. My hack/kludge/work-around
was to sleep for a max of 5ms, but that is not a clean, or efficient
solution. Another person sent private email to me claiming that he
saw the same problem, so it's likely I'm not insane on this issue :)

So, I do think there may be problems with select, but I'm not sure if it
relates to your problem or not.


Ben

>
> I'm not subsribed on the list, so when replying this you may consider
> Cc:ing me.
>
> --
> M. Tavasti / [email protected] / +358-40-5078254
> -
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/

--
Ben Greear <[email protected]> <[email protected]>
President of Candela Technologies Inc http://www.candelatech.com
ScryMUD: http://scry.wanfear.com http://scry.wanfear.com/~greear

2001-07-25 15:28:54

by M. Tavasti

[permalink] [raw]
Subject: Re: Select with device and stdin not working

"Richard B. Johnson" <[email protected]> writes:

> Change:
> } else if(FD_ISSET(fileno(stdin),&rfds) ) {
> To:
> } if(FD_ISSET(fileno(stdin),&rfds) ) {
>
> Both of these bits can be (probably are) set.

You are third person to suggest that. Yes, it's good point, but
doesn't make any difference. Or it makes when both device and stdin
have something, stdin is read on second round.

But now there is nothing coming from device, and typing + pressing
enter won't make select() return like it should.

Same binary works fine with 2.0.X kernels, or if I'm having stdin
+ pipe (named or unnamed, doesn't matter). And when trying with 2.0
kernel, system was totally same except kernel version.

Anybody, can you get select working *properly* with stdin+/dev/random?
If you can, then there must be some mistake on my code.

--
M. Tavasti / [email protected] / +358-40-5078254
Poista s?hk?postiosoitteesta molemmat x-kirjaimet
Remove x-letters from my e-mail address

2001-07-25 15:46:57

by Richard B. Johnson

[permalink] [raw]
Subject: Re: Select with device and stdin not working

On 25 Jul 2001, M. Tavasti wrote:

> "Richard B. Johnson" <[email protected]> writes:
>
> > Change:
> > } else if(FD_ISSET(fileno(stdin),&rfds) ) {
> > To:
> > } if(FD_ISSET(fileno(stdin),&rfds) ) {
> >
> > Both of these bits can be (probably are) set.
>
> You are third person to suggest that. Yes, it's good point, but
> doesn't make any difference. Or it makes when both device and stdin
> have something, stdin is read on second round.
>
> But now there is nothing coming from device, and typing + pressing
> enter won't make select() return like it should.

It works here...........


#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/poll.h>
#include <errno.h>
#include <string.h>

static const char dev[]="/dev/random";

int main(int args, char *argv[])
{
int fd, retval;
fd_set rfds;

if((fd = open(dev, O_RDONLY)) < 0)
{
fprintf(stderr, "Can't open device, %s\n", dev);
exit(EXIT_FAILURE);
}
for(;;)
{
FD_ZERO(&rfds);
FD_SET(fd, &rfds);
FD_SET(STDIN_FILENO, &rfds);
retval = select(fd+1, &rfds, NULL, NULL, NULL);
if(retval < 0)
fprintf(stderr, "Error was %s\n", strerror(errno));
printf("Return = %d\n", retval);
if(FD_ISSET(fd, &rfds))
printf("Input is available from %s\n", dev);
if(FD_ISSET(STDIN_FILENO, &rfds))
printf("Input is available from %s\n", "terminal");
}
if(close(fd) < 0)
{
fprintf(stderr, "Can't close device, %s\n", dev);
exit(EXIT_FAILURE);
}
return 0;
}




Cheers,
Dick Johnson

Penguin : Linux version 2.4.1 on an i686 machine (799.53 BogoMips).

I was going to compile a list of innovations that could be
attributed to Microsoft. Once I realized that Ctrl-Alt-Del
was handled in the BIOS, I found that there aren't any.


2001-07-26 12:07:47

by M. Tavasti

[permalink] [raw]
Subject: Re: Select with device and stdin not working

"Richard B. Johnson" <[email protected]> writes:

> > But now there is nothing coming from device, and typing + pressing
> > enter won't make select() return like it should.
>
> It works here...........

You're testing different thing. You're not reading anything, so at
least I get endlessly 'Input is available from /dev/random', and
whenever you type something, also in terminal there's data available.
If nobody reads data from /dev/random, of course there is data
availble.

I modified your program (see end), and results: on 2.2.19 and 2.2.16
everything works ok, in 2.4.5 not, terminal input (with return)
randomly makes select return. When looking from random.c, in 2.2.19
poll_wait is called once, like this:

poll_wait(file, &random_poll_wait, wait);

And in 2.4.5:

poll_wait(file, &random_read_wait, wait);
poll_wait(file, &random_write_wait, wait);


I think I got idea how to do it right, make one wait queue for poll,
which is woken up when read OR write queue is woken up.

So, now everybody just check your driver how does it do poll.


----

Here is modified test. Try this to get real results:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/poll.h>
#include <errno.h>
#include <string.h>

static const char dev[]="/dev/random";

int main(int args, char *argv[])
{
int fd, retval;
fd_set rfds;
char buff[1024];

if((fd = open(dev, O_RDONLY)) < 0)
{
fprintf(stderr, "Can't open device, %s\n", dev);
exit(EXIT_FAILURE);
}
for(;;)
{
FD_ZERO(&rfds);
FD_SET(fd, &rfds);
FD_SET(STDIN_FILENO, &rfds);
retval = select(fd+1, &rfds, NULL, NULL, NULL);
if(retval < 0)
fprintf(stderr, "Error was %s\n", strerror(errno));
printf("Return = %d\n", retval);
if(FD_ISSET(fd, &rfds)) {
printf("Input is available from %s\n", dev);
read(fd,buff,1024);
}
if(FD_ISSET(STDIN_FILENO, &rfds)) {
printf("Input is available from %s\n", "terminal");
read(STDIN_FILENO,buff,1024);
}

}
if(close(fd) < 0)
{
fprintf(stderr, "Can't close device, %s\n", dev);
exit(EXIT_FAILURE);
}
return 0;
}

--
M. Tavasti / [email protected] / +358-40-5078254
Poista s?hk?postiosoitteesta molemmat x-kirjaimet
Remove x-letters from my e-mail address

2001-07-26 14:04:03

by M. Tavasti

[permalink] [raw]
Subject: Re: Select with device and stdin not working

"M. Tavasti" <[email protected]> writes:

> randomly makes select return. When looking from random.c, in 2.2.19
> poll_wait is called once, like this:
>
> poll_wait(file, &random_poll_wait, wait);
>
> And in 2.4.5:
>
> poll_wait(file, &random_read_wait, wait);
> poll_wait(file, &random_write_wait, wait);
>
>
> I think I got idea how to do it right, make one wait queue for poll,
> which is woken up when read OR write queue is woken up.

After testing with my own driver, using just one poll_wait doesn't
make difference in 2.4.5.

--
M. Tavasti / [email protected] / +358-40-5078254
Poista s?hk?postiosoitteesta molemmat x-kirjaimet
Remove x-letters from my e-mail address