[Date Prev][Date Next] [Chronological] [Thread] [Top]

Memory (Socket/Handle) leak in libldap



Hi!
I've found what I think is a bug, and need some help confirming it.
I'm using the OpenLDAP 1.2.11 libraries on NT 4.0 to connect to an OpenLDAP
1.2.9 server running on RedHat Linux 6.2.

Everything runs OK, until the client can't connect to the server.  This
happens during heavy load occasionally.  I've simulated the situation by
stopping the OpenLDAP server daemon.  When the daemon is stopped, the number
of handles associated with my app increases with each attempt to connect to
the LDAP server via ldap_connect_to_host (libldap: os-ip.c).  The problem is
that these handles never get closed.

Here's the partial source code for reference:

===================================================================
ldap_connect_to_host( Sockbuf *sb, char *host, unsigned long address,
	int port, int async )
.
.
.
	rc = -1;
	for ( i = 0; !use_hp || ( hp->h_addr_list[ i ] != 0 ); i++ ) {
		if (( s = socket( AF_INET, SOCK_STREAM, 0 )) < 0 ) {
			return( -1 );
		}

#ifdef TCP_NODELAY
		status = 1;
		if( setsockopt( s, IPPROTO_TCP, TCP_NODELAY,
			(char *) &status, sizeof(status)) == -1 )
		{
			Debug( LDAP_DEBUG_ANY, "setsockopt(TCP_NODELAY) failed on %d\n",
			    s, 0, 0 );
		}
#endif
.
.
.
		if ( connect( s, (struct sockaddr *)&sin,
		    sizeof( struct sockaddr_in )) >= 0 ) {
			connected = 1;
			rc = 0;
			break;
		} else {
#ifdef HAVE_WINSOCK
			errno = WSAGetLastError();
#endif
.
.
.
#ifdef LDAP_DEBUG
			if ( ldap_debug & LDAP_DEBUG_TRACE ) {
				perror( (char *)inet_ntoa( sin.sin_addr ));
			}
#endif
			tcp_close( s );
                                  // <------ closehandle(s);
			if ( !use_hp ) {
				break;
			}
		}
	}

	sb->sb_sd = s;

	if ( connected ) {
.
.
.
		Debug( LDAP_DEBUG_TRACE, "sd %d connected to: %s\n",
		    s, (char *) inet_ntoa( sin.sin_addr ), 0 );
	}

	return( rc );
}
================================================================

In this case the socket call passes, but the connect call fails.  A pair of
handles are opened by these calls; one for \Device\Afd\Endpoint and one for
\Device\Tcp.  When the connect fails it calls tcp_close and passes in the
socket.  By debugging I found that tcp_close tries to validate the "file
handle" (socket) passed in and in this case it flags it as invalid and does
nothing with it.  The socket passed in is usually in the 1800 range.  My
application attempts to do cleanup by calling WSACleanup() - this is
supposed to close any remaining open sockets.  This doesn't seem to work,
maybe because the socket was not actually opened in the first place.  As a
result, I get an additional pair of handles each pass of my app.  These grow
pretty fast in a test environment.

I've "fixed" this by adding closehandle(s) after the tcp_close(s) (see
above).

This sure looks like a bug to me.  Can someone confirm this - and/or show me
a better way to fix it?

Thanks,

Dave Nelson
APEX Voice Communications










My application tries to cleanup remaining