Unix Programming - select does not return on input

This is Interesting: Free IT Magazines  
Home > Archive > Unix Programming > April 2004 > select does not return on input





You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

Author select does not return on input
gfgf

2004-04-22, 9:37 am

Hi all,

I'm using select() to read a few serial ports. After starting the
program it handles input on the first device where data arrives. When
data arrives on another device, select() does not wake up. Only data on
the first device wakes up select(). The interrupts show up in procinfo.
It doesn't matter whether a device on the multiport card or the mobo has
input, the line printf("res: %d\n", res); is not reached.

Any help appreciated!!!

Regards, Godfried

sample code:
FD_ZERO(&fds);
for(i = 0; i < numdevices; i++) {
strcpy(port[i].device, argv[i + 2]);
init_port(&(port[i]));
FD_SET(port[i].fd, &fds);
sprintf(device, "out_%s", basename(port[i].device));
if((fp[i] = fopen(device, "a")) == NULL) perror("fopen");
}

while(1) {
res = select(port[numdevices - 1].fd + 1, &fds, NULL, NULL, NULL);
printf("res: %d\n", res);
for(i = 0; i < numdevices; i++) {
if(FD_ISSET(port[i].fd, &fds)) {
while((n = read_line(&port[i], buf, ENDCH, sizeof buf)) > 0) {
if(n < 0) {
perror("read");
sleep(1);
continue;
}
fwrite(buf, n, 1, fp[i]);
fflush(fp[i]);
printf("%s: %s (%d)\n", port[i].device, buf, n);
}
}
}
}


Barry Margolin

2004-04-22, 10:44 am

In article <4087c60e$0$36169$e4fe514c@news.xs4all.nl>,
gfgf <gfxtra2000@yahoo.co.uk> wrote:

> Hi all,
>
> I'm using select() to read a few serial ports. After starting the
> program it handles input on the first device where data arrives. When
> data arrives on another device, select() does not wake up. Only data on
> the first device wakes up select(). The interrupts show up in procinfo.
> It doesn't matter whether a device on the multiport card or the mobo has
> input, the line printf("res: %d\n", res); is not reached.


You're making one of the most common select() mistakes: you need to call
FD_SET() every time through the loop, since select() modifies fds. Or
more simply, you can make a copy of fds before the loop:

saved_fds = fds;
while (1) {
fds = saved_fds;
res = select(...);
...
}

--
Barry Margolin, barmar@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
gfgf

2004-04-22, 11:36 am

Barry Margolin wrote:

> You're making one of the most common select() mistakes: you need to

call
> FD_SET() every time through the loop, since select() modifies fds. Or
> more simply, you can make a copy of fds before the loop:
>
> saved_fds = fds;
> while (1) {
> fds = saved_fds;
> res = select(...);
> ...
> }


Hi Barry,

Thanks for your response. Tried that, didn't work at first. It appeared
that I had managed to go into another infinite while() loop after the
first return from select().
How stupid can one be... Now it works as expected.

Must be related to lack of sleep, worries about the cat not coming home
and the income taxes. :-)

Regards,
Godfried

Nils O. Selåsdal

2004-04-22, 11:36 am

On Thu, 22 Apr 2004 15:19:21 +0200, gfgf wrote:

> Hi all,
>
> I'm using select() to read a few serial ports. After starting the
> program it handles input on the first device where data arrives. When
> data arrives on another device, select() does not wake up. Only data on
> the first device wakes up select(). The interrupts show up in procinfo.
> It doesn't matter whether a device on the multiport card or the mobo has
> input, the line printf("res: %d\n", res); is not reached.
>
> Any help appreciated!!!
>
> Regards, Godfried
>
> sample code:
> FD_ZERO(&fds);
> for(i = 0; i < numdevices; i++) {
> strcpy(port[i].device, argv[i + 2]);
> init_port(&(port[i]));
> FD_SET(port[i].fd, &fds);
> sprintf(device, "out_%s", basename(port[i].device));
> if((fp[i] = fopen(device, "a")) == NULL) perror("fopen");

select'ing on filedescritors, but reading through a FILE* can
cause surprising results if you're not careful.

> }
>
> while(1) {


"fds" will be modified to hold only ready descriptors, so you
need to initialize them correctly at each select call. e.g.:
fd_set rfds = fds;
and use the rfds in your code below, not fds.
If you need to remove/add filedescriptors , do that to fds.

> res = select(port[numdevices - 1].fd + 1, &fds, NULL, NULL, NULL);
> printf("res: %d\n", res);
> for(i = 0; i < numdevices; i++) {
> if(FD_ISSET(port[i].fd, &fds)) {
> while((n = read_line(&port[i], buf, ENDCH, sizeof buf)) > 0) {
> if(n < 0) {
> perror("read");
> sleep(1);
> continue;
> }
> fwrite(buf, n, 1, fp[i]);
> fflush(fp[i]);
> printf("%s: %s (%d)\n", port[i].device, buf, n);
> }
> }
> }
> }


--
Nils Olav Selåsdal
System Engineer
w w w . u t e l s y s t e m s . c o m


Sponsored Links






Free braindumps | Software forum | Database administration forum

Copyright 2003 - 2008 webservertalk.com