tonymontana
tonymontana

Reputation: 5823

getsockopt() returns EINPROGRESS in non blocking connect()+select() flow

Update:

My bad. The error I am getting is ECONNREFUSED and not EINPROGRESS. After checking the error variable I've 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);  

Upvotes: 2

Views: 21234

Answers (3)

Aditya Sehgal
Aditya Sehgal

Reputation: 2883

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

Upvotes: 4

caf
caf

Reputation: 239171

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.

Upvotes: 3

Chris Arguin
Chris Arguin

Reputation: 11998

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.

Upvotes: 2

Related Questions