You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@apr.apache.org by Jakob Praher <ja...@dynatrace.com> on 2006/04/12 10:43:22 UTC

apr_socket_connect

hi all,

apparently I have a strange problem with apr_socket_connect, when 
calling it several times within a short time period, it turns out to 
return APR_SCUCESS without actually succeeded in connect( )ing!

After some research I found out, that on my machine (SUSE Linux 9.3, 
uname=2.6.11.4-21.11-smp), the section of problem is the call to 
getsockopt( ... SO_ERROR ... ) because:

after that:
- error is 0
- rc = 0
- errno is 115

normally error would not be 0 and therefore the block would exit with
if (error) {
	return error;
}

but since it getsockopt( ) fills in &error with 0 the flow continues 
past the next guard:

if (rc == -1 && errno != EISCONN) {
	return errno;
}

and eventually returns APR_SUCCESS!!!

My question is:
Do you know if this is a bug in the SUSE maintained kernel. *Can* 
getsockopt, according to its definition, behave like this, if connect( ) 
was not successful?

SOLUTION:

I would definitely keep the old rc when checking  calling getsockopt. 
This would lead to a more pessimistic error detection and would not 
render apr_socket_connect( ) falsly returning APR_SUCCESS without a 
connection as in my case!

For instance the following change:

1 : #ifdef SO_ERROR
2 :        {
3 :            	int error;
4 :	    	int rc_sockopt = rc;
5 :            	apr_socklen_t len = sizeof(error);
6 :            	if ((rc_sockopt = getsockopt(sock->socketdes,
7 :			SOL_SOCKET, SO_ERROR,
8 :                                 (char *)&error, &len)) < 0) {
9 :                return errno;
10:            	}
11:		if (error) {
12:               	return error;
13:            	}
14:        }
15: #endif /* SO_ERROR */

line 4,5 use a rc_sockopt instead of overwriting the outer rc. This 
would leave the final check to return the errno,

if (rc == -1 && errno != EISCONN) {
     return errno;
}

thanks in advance
-- Jakob


Re: apr_socket_connect

Posted by Jakob Praher <ja...@dynatrace.com>.
hi jeff,



Jeff Trawick wrote:
> On 4/12/06, Jakob Praher <ja...@dynatrace.com> wrote:
>>hi all,
>>
>>apparently I have a strange problem with apr_socket_connect, when
>>calling it several times within a short time period, it turns out to
>>return APR_SCUCESS without actually succeeded in connect( )ing!
> 
> What socket options have you set on the socket?  timeout or just non-blocking?

blocking with timeout, the following settings apply:

apr_socket_opt_set(mpSocket, APR_TCP_NODELAY, 1);
apr_socket_timeout_set(mpSocket, 30*1000000LL );

everything else is as is.

> 
> If you set it to non-blocking, did you wait for the APR_POLLOUT
> condition with apr_poll() on the socket before calling
> apr_socket_connect again?  I think the error from getsockopt() is
> reset once it is retrieved the first time.  That may be the issue
> triggered with calling apr_socket_connect() multiple times.
> 
see above. it is a vanilla blocking socket.

> I wouldn't suspect a bug in the kernel for this, or many applications
> would fail.
> 
it is interesting though.
it boils really down to that, it is due to getsockopt.

--
Jakob


Re: apr_socket_connect

Posted by Jeff Trawick <tr...@gmail.com>.
On 4/12/06, Jakob Praher <ja...@dynatrace.com> wrote:
> hi all,
>
> apparently I have a strange problem with apr_socket_connect, when
> calling it several times within a short time period, it turns out to
> return APR_SCUCESS without actually succeeded in connect( )ing!

What socket options have you set on the socket?  timeout or just non-blocking?

If you set it to non-blocking, did you wait for the APR_POLLOUT
condition with apr_poll() on the socket before calling
apr_socket_connect again?  I think the error from getsockopt() is
reset once it is retrieved the first time.  That may be the issue
triggered with calling apr_socket_connect() multiple times.

I wouldn't suspect a bug in the kernel for this, or many applications
would fail.