Select with device and stdin not working

Select with device and stdin not working

Post by M. Tavast » Thu, 26 Jul 2001 21:30:09



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) ) {
                 ......
                }
        }

Quote:}

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.

--

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in

More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

 
 
 

Select with device and stdin not working

Post by Ketil Froy » Thu, 26 Jul 2001 22:20:06



Quote:> 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

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in

More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

 
 
 

Select with device and stdin not working

Post by M. Tavast » Thu, 26 Jul 2001 22:40:11



> > 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.

--

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in

More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

 
 
 

Select with device and stdin not working

Post by Stephen Landamor » Thu, 26 Jul 2001 23:20:10


Quote:> 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

--

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

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in

More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

 
 
 

Select with device and stdin not working

Post by Ketil Froy » Thu, 26 Jul 2001 23:20:12



Quote:> 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

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in

More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

 
 
 

Select with device and stdin not working

Post by Richard B. Johnso » Fri, 27 Jul 2001 00:10:08




> > 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,
* 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.

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in

More majordomo info at  http://www.veryComputer.com/
Please read the FAQ at  http://www.veryComputer.com/

 
 
 

Select with device and stdin not working

Post by Richard B. Johnso » Fri, 27 Jul 2001 00:50:12




> > 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;

Quote:}

Cheers,
* 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.

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in

More majordomo info at  http://www.veryComputer.com/
Please read the FAQ at  http://www.veryComputer.com/

 
 
 

Select with device and stdin not working

Post by M. Tavast » Fri, 27 Jul 2001 21:10:10



Quote:> > 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;

Quote:}

--

 Poista s?hk?postiosoitteesta molemmat x-kirjaimet
     Remove x-letters from my e-mail address
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in

More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/
 
 
 

Select with device and stdin not working

Post by M. Tavast » Fri, 27 Jul 2001 23:10:07



> 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.

--

 Poista s?hk?postiosoitteesta molemmat x-kirjaimet
     Remove x-letters from my e-mail address
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in

More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/