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.
Signature · 1 line
M. Tavasti / [email protected] / +358-40-5078254
Quoted 7 lines · M. Tavasti
Here program where I get problems:
int fd;
fd_setrfds;fd =
open("/dev/random", O_RDWR );
Quoted 14 lines
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
Quoted 5 lines · Ketil Froyn
Quoted 5 lines
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)
Quoted 4 lines
Quoted 1 line
}
It looks like you are sending the original
fd_setto 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.
Signature · 1 line
M. Tavasti / [email protected] / +358-40-5078254
Quoted 5 lines · M. Tavasti
But one would at least expect
FD_ZERO()to really clean up rfds, and after itFD_SET()is used again, for every call ofselect(). 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 ofselect()but something else.
Sorry, my bad. I misread your code.
Ketil
Quoted 29 lines · M. Tavasti
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_setrfds;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) ) { ...... } } }
Quoted 8 lines
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/randomis 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
Quoted 11 lines
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/
Signature · 3 lines
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
Quoted 15 lines · Ben Greear
Quoted 14 lines · M. Tavasti
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_setrfds;fd =
open("/dev/random", O_RDWR );
Quoted 14 lines
Quoted 6 lines
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");Quoted 8 lines
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.
Quoted 6 lines · Richard B. Johnson
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.
Signature · 3 lines
M. Tavasti / [email protected] / +358-40-5078254 Poista sähköpostiosoitteesta molemmat x-kirjaimet Remove x-letters from my e-mail address
Quoted 7 lines · M. Tavasti
Quoted 5 lines · Richard B. Johnson
Change:
} else if(FD_ISSET(fileno(stdin),&rfds) ) { To: } if(FD_ISSET(fileno(stdin),&rfds) ) {
Quoted 8 lines
Quoted 1 line
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.
Quoted 4 lines · Richard B. Johnson
Quoted 2 lines
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;
}Signature · 3 lines
M. Tavasti / [email protected] / +358-40-5078254 Poista sähköpostiosoitteesta molemmat x-kirjaimet Remove x-letters from my e-mail address
Quoted 5 lines · M. Tavasti
randomly makes select return. When looking from
random.c, in 2.2.19poll_waitis called once, like this:poll_wait(file, &random_poll_wait, wait);
Quoted 8 lines
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.
Signature · 3 lines
M. Tavasti / [email protected] / +358-40-5078254 Poista sähköpostiosoitteesta molemmat x-kirjaimet Remove x-letters from my e-mail address