1

old version

FD_ZERO(&rfds);
FD_ZERO(&master);
FD_SET(sockserver, &master);
fdmax =  sockserver;

for(;;) {
    rfds = master;
    if( select(fdmax+1, &rfds, NULL, NULL, NULL) == -1) {
        perror("select");
        exit(1);
    }

new version

FD_ZERO(&rfds);
FD_ZERO(&master);
FD_SET(sockserver, &master);
fdmax =  sockserver;

for(;;) {
    FD_ZERO(&rfds);
    for(j=0;j<max_socket;j++){
        if(FD_ISSET(j,&master))
            FD_SET(j,&rfds);
    }
    /* Not copying directly, because you can't assume that the set is integer type.
         It may be anything. */
    if( select(fdmax+1, &rfds, NULL, NULL, NULL) == -1) {
        perror("select");
        exit(1);
    }

I tried old version and will crash when run to select(), then I searched new version and try, it's still crash. I also tried to move out all local variables that I thought it might be stack overflow, but it still crash.

Can someone answer this problem? Thanks a lot.

user1021319
  • 117
  • 1
  • 1
  • 6
  • What's `max_socket` set to? Why isn't that `fdmax + 1`? – Jonathan Leffler Jul 07 '15 at 02:22
  • 1
    This is a long shot, but check that sockserver is less than FD_SETSIZE. – Craig S. Anderson Jul 07 '15 at 02:23
  • 1
    Also, on BSD at least, there is `void FD_COPY(fd_set *fdset_orig, fd_set *fdset_copy);` — with cack-handed '(src, dst)' arguments instead of '(dst, src)' like most other copy functions (`strcpy()`, `memmove()`, etc). Unfortunately, POSIX doesn't standardize it (see [`FD_CLR()`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/FD_CLR.html)); I wonder if that's because of divergent implementations. Linux (Ubuntu 14.04 LTS checked) doesn't seem to have `FD_COPY`. – Jonathan Leffler Jul 07 '15 at 02:35
  • 1
    You might also notice that POSIX [``](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_select.h.html) says: _The `` header shall define the `fd_set` type as a structure._ There's at least a moderate chance you can use structure copy, unless you're tinkering with its size — see [Are there any platforms where using structure copy on an `fd_set` causes problems?](http://stackoverflow.com/questions/2421672) and my [answer](http://stackoverflow.com/a/2436796/15168) there. (Maybe that needs an update 5 years later?) – Jonathan Leffler Jul 07 '15 at 02:50
  • regarding this line: 'rfds = master;' both of these items are structs that contain several fields. so a simple assignment will not work. Suggest using memcpy(&rfds, &master, sizeof( rfds ) ); – user3629249 Jul 08 '15 at 06:12

1 Answers1

2

On both versions, you are not setting fdmax correctly. If any sockets in the master are greater than the value of sockserver, select() will ignore them. The first parameter of select() must be +1 higher than the largest socket in rfds.

Also, in the old version, there is no guarantee that rfds = master is a valid operation. On platforms where it is potentially wrong, use FD_COPY() instead:

FD_COPY(&master, &rfds); 

But in this case, by using the new version, you do not need to use FD_COPY() (if it is available).

And as Craig stated in comments, make sure max_socket is actually valid, does not exceeding FD_SETSIZE, etc.

Try this:

FD_ZERO(&master);
FD_SET(sockserver, &master);
...    

FD_ZERO(&rfds);
fdmax = -1;
for(j = 0; (j < max_socket) && (j < FD_SETSIZE); ++j){
    if (FD_ISSET(j, &master)) {
        FD_SET(j, &rfds);
        fdmax = j;
    }
}
if (select(fdmax+1, &rfds, NULL, NULL, NULL) == -1) {
    perror("select");
    exit(1);
}
...

If you are still having problems, then you need to provide a more realistic MCVE demonstrating the problem in action.

Community
  • 1
  • 1
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770