tags:

views:

1862

answers:

3

Update:

My BAD. The error I am getting is ECONNREFUSED and not EINPROGRESS. After I had checked the %error% variable and found that it is greater than 0, I printfed errno instead of %error%. Of course errno is EINPROGRESS because it value didn't change since the call to connect().

Question answered. Thanks folks.

I am using the the the same piece of code as in Stevens' UNIX Network Programming non >blocking connect() example:

  1. Setting socket to nonblocking
  2. Initiate nonblocking connect()
  3. Check for immediate completion
  4. Call select() with timeout and wait for read or write readiness
  5. When select() returns with value greater than 0 do getsockopt(socket, SOL_SOCKET, SO_ERROR, &error, &len).

The error I am getting is EINPROGRESS. The code is executed on rhel5 server.

Any ideas why I am getting this error?

Code snippet:

flags = fcntl(sockfd, F_GETFL, 0);
fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);

if ((retVal = connect(sockfd, saptr, salen)) < 0)
    if (errno != EINPROGRESS)
 return (-1);

if (retVal == 0)
{
    // restore file status flags
    fcntl(sockfd, F_SETFL, flags);  
    return 0;
}

FD_ZERO(&rset);
FD_SET(sockfd, &rset);
wset = rset;
tval.tv_sec = nsec;
tval.tv_usec = 0;

if ((retVal = select(sockfd + 1, &rset, &wset, NULL, &tval)) == 0) 
{
    // timeout
    close(sockfd);          
    errno = ETIMEDOUT;
    return (-1);
}

if (retVal < 0) 
{
    // select() failed
    return (-1);
}

if (FD_ISSET(sockfd, &rset) || FD_ISSET(sockfd, &wset)) 
{
    len = sizeof(error);
    error = 0;
    if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &len) < 0)
 return (-1);     

    if (error > 0) //<<<<< error == EINPROGRESS >>>
    { 
 close(sockfd);
 errno = error;
 return (-1);
    }
} 
else
{
    return (-1);
}

// restore file status flags
fcntl(sockfd, F_SETFL, flags);
+1  A: 

A select value greater than zero doesn't indicate any sort of error... it is the number of sockets that met the criteria of the select statement. select will return -1 in the event of a failure.

It's not clear to me when calling getsocktopt with SO_ERROR is valid; you are probably best of sticking with checking for errors everytime you use the socket ( which I think you are doing anyway ). It the select isn't failing, you are fine.

Chris Arguin
There is no problem with select(). the call to getsockopt() is made here to check whether the non blocking connect() succeeded or not. In my case it didn't.
error.exit
+1  A: 

EINPROGRESS indicates that the non-blocking connect() is still... in progress.

So I would ask - are you checking that after the select() returns, the connect()ing file descriptor is still set in the writefds fd_set? If it isn't, then that means select() has returned for some other reason.

caf
+2  A: 

Shucks....I give up. I tried and tried but could not find a problem with your code. So, all I offer are some suggestions and hypothesis.

  • Use FD_COPY to copy rset to wset.

  • Can you do a getsockopt when the first connect fails. I am suspecting that Select is returning 0 and because of above, somehow your writefd set is set and doing a getsockopt is returning you the stale error from the previous connect. IMO, a subsquent connect should return EALREADY (although it could be platform dependant)

Please do the above (and downvote me if I am wrong about using FD_COPY) and share the results

Aditya Sehgal
Aditya, I found the problem and edited my original question with description of the problem. It is my bad. I printfed the wrong value inside "if (error > 0)" block (the relevant printf is no in the code snippet). Thank you very much for your help.
error.exit
Grand job. All's well then.
Aditya Sehgal