Solved

Never ready to read

Posted on 1998-04-24
12
285 Views
Last Modified: 2010-04-15
Hi, I've taken many of your suggestions already and here is
the new improved version! Unfortunately it still acts like stdin is never ready to be read from, any suggestions? The other socket works just fine for reading etc...

void ConnectionIO(Sock *NSock)
             /* In this function, first we set up everything for our
                select calls. Then we loop, first reading in the data
                that needs to be read, then writing out any buffers */
{
  fd_set rset;
  int i, result;
  Sock Input;

  InitSock(&Input);
  Input.sock_fd = STDIN_FILENO;
  Input.name = "Standard Input, FUN!";
  Input.out_fd = NSock->sock_fd;                              NSock->out_fd = STDOUT_FILENO;
  FD_ZERO(&rset);
  FD_SET(STDIN_FILENO, &rset); /* 0 is stdin */
  FD_SET(NSock->sock_fd, &rset);

  while(1)
  {
    result = select(NSock->sock_fd + 1, &rset, NULL, NULL, NULL);

    if(result < 0) /* Whoops, looks like we've got an error */                          
      perror("JWClient:");
      exit(1);
    }
    if (FD_ISSET(NSock->sock_fd, &rset))
      ReadSock(NSock);
    if (FD_ISSET(Input.sock_fd, &rset))
      ReadSock(&Input);
  } /* While */
} /* ConnectionIO */

                               
0
Comment
Question by:jwilcox
  • 3
  • 3
  • 3
  • +2
12 Comments
 
LVL 5

Expert Comment

by:julio011597
ID: 1255686
I can see a few problems in your function:

1. a NULL pointer as a timeout in select() - at least on my OS - makes your function block indefinitely... is this what happens? To poll, the timeout parameter should be a nonzero value and point to a zero-valued timeval structure.

2. if the time limit expires before any event occurs that would cause one of the masks to be set to a non-zero value, select() completes successfully and returns 0 (zero). Your code is exiting with an error notification, instead.

3. you should not loop around FD_ISSET(); just give it the file descriptor to check:

if(FD_ISSET(NSock->sock_fd, &rset)) ReadSock(NSock->sock_fd);
0
 
LVL 5

Expert Comment

by:julio011597
ID: 1255687
Hey jwilcox, did that help? did i miss the point?
0
 
LVL 1

Author Comment

by:jwilcox
ID: 1255688
Actually, while I definatly appreciate the help, it hassn't helped. I have it as NULL because I do want it to block indefinitly...and even when I axed the loop when i gets to the FD to check it, it still acts like that bit wasn't changed...even though if I do a read right before that select call, I get plenty of data, but take that read out and depend only on select, and down the drain it goes...here is some more info from GDB if this will help you at all...
 NSock->sock_fd = 9  rset = {fds_bits = {513, 0 <repeats 31 times>} }
 
 That rset is after both the calls to FD_SET()...thanks in advance.
 
0
PRTG Network Monitor: Intuitive Network Monitoring

Network Monitoring is essential to ensure that computer systems and network devices are running. Use PRTG to monitor LANs, servers, websites, applications and devices, bandwidth, virtual environments, remote systems, IoT, and many more. PRTG is easy to set up & use.

 
LVL 4

Expert Comment

by:jos010697
ID: 1255689
I noticed one thingy; shouldn't the select line read:

    result = select(NSock->sock_fd+1, &rset, &wset, NULL, NULL);

i.e. the first parameter equals the _number_ of file descriptors to check ...

kind regards,

Jos aka jos@and.nl

ps. It still doesn't explain why stdin is never readable though ...
0
 
LVL 1

Author Comment

by:jwilcox
ID: 1255690
Edited text of question
0
 
LVL 5

Expert Comment

by:julio011597
ID: 1255691
This may sound stupid, but should that work for stdin and stdout after all?
I mean, they are file descriptors, not socket descriptors!?

I guess i'm going to dive the Sockets FAQ again :)
0
 
LVL 4

Expert Comment

by:jos010697
ID: 1255692
Julio, you've got a point here: on (any? every?) unix box sockets, files, etc are
all implemented as streams. Not so on NT or Windows/95 boxes; I've seen it
actually happen (someone tried to fdopen a socket on an NT box). There's
a disctinction between file descriptors and socket descriptors on those machines ...

I don't know what moron invented that ...

kind regards,

Jos aka jos@and.nl
0
 
LVL 2

Expert Comment

by:seedy
ID: 1255693
Here is an excerpt from man pages for select.
"On successful completion, the objects pointed to by the readfs,
writefs, and errorfds arguments are ***modified*** to indicate
which file descriptors are ready for reading, ready for writing,
or have an error condition pending, respectively."

This means, in your code, after returning from select, the
content of  "rset" is modified! - or the bit is set ONLY for
the FD that is ready for a read.  On next iteration, you
will only check for that FD!

So can you place the FD_ZERO, FD_SET statements just before the
select call - inside the loop - and tell us what happens?
0
 
LVL 4

Expert Comment

by:jos010697
ID: 1255694
Julio, you've got a point here: on (any? every?) unix box sockets, files, etc are
all implemented as streams. Not so on NT or Windows/95 boxes; I've seen it
actually happen (someone tried to fdopen a socket on an NT box). There's
a disctinction between file descriptors and socket descriptors on those machines ...

I don't know what moron invented that ...

kind regards,

Jos aka jos@and.nl
0
 
LVL 1

Author Comment

by:jwilcox
ID: 1255695
Seedy was correct...if you don't re-setup your FD_ZERO FD_SET everytime it will have the problems, but now it works fine, so thank you very much!
0
 
LVL 1

Expert Comment

by:szetoa
ID: 1255696
Hi jwilcox,

I have a comment about your routine and hope this helps.
The select() looks OK to me except where the data for the
stdin come from.  I did not see any statement 'reading'
from stdin.  If there is no data 'already' in stdin, the
select() will block indefinitely.  If you are running your
program under UNIX, you may try:

    echo "some garbage" | pgm

Assuming your program name is 'pgm'.  I think in this case,
you will see your select() statement works.

Hope this help.
0
 
LVL 2

Accepted Solution

by:
seedy earned 100 total points
ID: 1255697
You need to re-initialize the read, write, error fd sets every
time you call the 'select' statement. Place the FD_ZERO, FD_SET
statements just before the select call, inside the loop.
0

Featured Post

Are your AD admin tools letting you down?

Managing Active Directory can get complicated.  Often, the native tools for managing AD are just not up to the task.  The largest Active Directory installations in the world have relied on one tool to manage their day-to-day administration tasks: Hyena. Start your trial today.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
memory leak detection 9 94
Pointer in one class to member in another 6 125
UPD maximums on Red Hat 6 122
smtp c source code 7 88
Have you thought about creating an iPhone application (app), but didn't even know where to get started? Here's how: ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ Important pre-programming comments: I’ve never tri…
Preface I don't like visual development tools that are supposed to write a program for me. Even if it is Xcode and I can use Interface Builder. Yes, it is a perfect tool and has helped me a lot, mainly, in the beginning, when my programs were small…
Video by: Grant
The goal of this video is to provide viewers with basic examples to understand and use for-loops in the C programming language.
Video by: Grant
The goal of this video is to provide viewers with basic examples to understand and use nested-loops in the C programming language.

828 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question