Solved

Never ready to read

Posted on 1998-04-24
12
277 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
 
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
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
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

6 Surprising Benefits of Threat Intelligence

All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

Join & Write a Comment

Summary: This tutorial covers some basics of pointer, pointer arithmetic and function pointer. What is a pointer: A pointer is a variable which holds an address. This address might be address of another variable/address of devices/address of fu…
Windows programmers of the C/C++ variety, how many of you realise that since Window 9x Microsoft has been lying to you about what constitutes Unicode (http://en.wikipedia.org/wiki/Unicode)? They will have you believe that Unicode requires you to use…
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.
The goal of this video is to provide viewers with basic examples to understand and use switch statements in the C programming language.

759 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

Need Help in Real-Time?

Connect with top rated Experts

22 Experts available now in Live!

Get 1:1 Help Now