Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

c++

c

unix

sockets

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);  
like image 753
tonymontana Avatar asked Aug 05 '26 16:08

tonymontana


2 Answers

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

like image 172
Aditya Sehgal Avatar answered Aug 08 '26 10:08

Aditya Sehgal


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.

like image 32
caf Avatar answered Aug 08 '26 10:08

caf



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!