UNIX Socket FAQ

A forum for questions and answers about network programming on Linux and all other Unix-like systems

You are not logged in.

  • Index
  • » General
  • » Select: Accepted connection never appear in readfds

#1 2011-10-28 10:57 PM

LSH
Member
Registered: 2011-10-28
Posts: 1

Select: Accepted connection never appear in readfds

Hi

I have written a web server using non-blocking socket with select (on Linux).
Some times when server accepts connection, connection never appears on read set (readfds). After 5 minutes connection is marked for close and removed from clients list.

My program is build on one of classics approach:
1. check/prepare clients structure for select (like add listen socked to read_set and etc)
2. select
3. process sets (readfds)
4. close connections, remove from list

Program looks like (more or less, some code was cut out, so there might be no error checks):

//1.prepare for select
 for (c = clients; c != NULL && can_run; c = c->next) {
            switch (c->status) {
                case CL_LISTEN_SD: //main listen socked 
                    FD_SET(c->socket_sd, &read_set); 
                  break;
                case CL_NEW: // new client connection
                    if (now - c->sec > MAX_WAIT_TIME_SEC) { //process time
                        cl_mark_for_close(c);
                        continue;
                    }
                    FD_SET(c->socket_sd, &read_set);
                  break;
(...)
//2.select
res = select(max_sd + 1, &read_set, &write_set, &e_set, &timeout);
(...)
//3. process sets
 for (c = clients; c != NULL && can_run; c = c->next) {
            if (c->status == CL_LISTEN_SD && FD_ISSET(c->socket_sd, &read_set) )
                do {
                    new_sd = accept(listen_sd, NULL, NULL);
                    if (new_sd < 0) {
                        if (errno != EWOULDBLOCK && errno != EAGAIN) {
                            perror("accept()");
                        }
                        break;
                    }
                    list_append(clients, new_client); // client status is CL_NEW
                } while (new_sd != -1);
                continue;
            }
            if (FD_ISSET(c->socket_sd, &read_set) || c->force_process) {
               //SOMETIMES client never gets here
            }
//4. (...)

Extending process time to 15 minutes doesn't help at all.
However:
When I use my favorite debug browser - telnet and I send request: 

GET / HTTP/1.0

... AND I added additional check recv with MSG_PEEK full request appear in buffer. Then I set force process flag for client (c->force_process) and handle request with standard recv (there is no error, especially EWOULDBLOCK, EAGAIN). Client is still not on read_set.

What happened in above example, why select "drop" some connections (a bug in select implementation) ?
Is it possible to force select to not clear connection from read_set ?
Is there any other work-around, solution for this problem ?

How to check socket is alive and ready to use, is there something more then: recv with MSG_PEEK and getsockopt with SO_ERROR:

res = recv(c->socket_sd, buffer, sizeof (buffer), MSG_PEEK);
getsockopt(c->socket_sd, SOL_SOCKET, SO_ERROR, &err &len);

Thanks
Lsh.

Offline

#2 2011-10-29 03:21 PM

i3839
Oddministrator
From: Amsterdam
Registered: 2003-06-07
Posts: 2,231

Re: Select: Accepted connection never appear in readfds

You just have a bug in your code somewhere, there's nothing wrong with select() itself.

Maybe max_sd isn't updated correctly every time. For instance, I see no checks for new_sd
against max_sd after the accept.

Or there may be an error with  c->sec having garbage values or some integer overflow problem.
I would at least print something out when you drop clients, so you can more easily see when that
happens.

Having a whole status field just for CL_LISTEN and CL_NEW is a bit overkill and makes things
only more complicated. I would just check the fd against a (globally declared) listen fd instead.

For debugging these kind of problems Strace can be very useful too. And compile with all
warnings enabled and run it through Valgrind just to be sure.

Offline

#3 2011-10-29 04:03 PM

RobSeace
Administrator
From: Boston, MA
Registered: 2002-06-12
Posts: 3,829
Website

Re: Select: Accepted connection never appear in readfds

Maybe max_sd isn't updated correctly every time. For instance, I see no checks for new_sd
against max_sd after the accept.

Yeah, that's exactly what I was thinking...  It's either that or something similar...  You'd really have to post your actual code though for us to find the true bug in it...  That chopped up partial code isn't all that helpful, since you leave out parts where the problem likely lies...  Specifically, the culprit is most likely in the part that accepts a new client...  And, you just jump from accept()'ing the new socket FD to this mystery list_append() function, which you pass something called "new_client" which you never seem to actually create in that code there, and never show what you do with the "new_sd" socket FD...

Offline

  • Index
  • » General
  • » Select: Accepted connection never appear in readfds

Board footer

Powered by FluxBB