I see at least two issues in your code. See below for specific comments.
ling qing wrote:
The sample code is as follows. Make command: g++ testmem.C lib/libldap-2.4.so.2 lib/libsasl2.so.2 lib/liblber-2.4.so.2 -Iinclude/ -Llib/ -DLDAP_DEPRECATED -g -lpthread If mode is normal, it's ok. If mode is TLS, there is memory leak even if you don't input bind dn. If mode is SSL, memory leak only happens when you input bind dn and password. The openLDAP lib is the latest release version 2.4.15.
I am sure that this is a bug of openLDAP.
#include "ldap.h" #include <string> #include <unistd.h>
using namespace std;
typedef enum LDAP_TRANS_METHOD {LDAP_TRANS_NORMAL, LDAP_TRANS_TLS, LDAP_TRANS_SSL};
LDAP_TRANS_METHOD transMethod = LDAP_TRANS_NORMAL; const char * host = NULL; const char * binddn = NULL; const char * bindpwd = NULL; int connectnum = 0;
void * connectLDAP(void * param) { LDAP * ld;
int rc; string url; if( transMethod == LDAP_TRANS_SSL ) url = "ldaps://"; else url = "ldap://"; if( host == NULL ) return NULL; url.append(host);
struct timeval tvout; tvout.tv_sec = 10; tvout.tv_usec = 0;
if( ldap_set_option( NULL, LDAP_OPT_NETWORK_TIMEOUT, &tvout ) !=
LDAP_OPT_SUCCESS ) { printf("ldap_set_option LDAP_OPT_NETWORK_TIMEOUT failed\n"); return NULL; }
rc = ldap_initialize(&ld, url.c_str()); if( rc != LDAP_SUCCESS || ld == NULL ) { printf("ldap_initialize failed!\n"); return NULL; }
if( transMethod == LDAP_TRANS_TLS || transMethod == LDAP_TRANS_SSL ) { int protocol = 3; if( ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &protocol ) != LDAP_OPT_SUCCESS ) { printf("ldap_set_option LDAP_OPT_PROTOCOL_VERSION failed\n"); return NULL; } int cert = 0; if( ldap_set_option( NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, &cert ) != LDAP_OPT_SUCCESS )
You're not supposed to call ldap_set_option() with NULL handler from within a threaded program, as libldap is thread-safe only when a specific handler is only used from within a single thread. I'm not discussing the case of this specific option, nor of its side-effects, if any, as I didn't investigate it and I'm not specifically familiar with that portion of code.
{ printf("ldap_set_option LDAP_OPT_X_TLS_REQUIRE_CERT failed\n"); return NULL; }
}
if( transMethod == LDAP_TRANS_TLS ) { rc = ldap_start_tls_s( ld, NULL, NULL ); if( rc != LDAP_SUCCESS ) { printf("ldap_start_tls_s failed\n"); return NULL; } }
if( binddn != NULL && bindpwd != NULL ) { rc = ldap_bind_s(ld, binddn, bindpwd, LDAP_AUTH_SIMPLE); if ( LDAP_SUCCESS != rc ) { printf("ldap_bind_s failed\n"); return NULL; } }
This code is filled with "return NULL;" without cleaning up memory if anything goes wrong. Are you sure everything is always going fine for all your threads during your tests?
ldap_unbind_s(ld); connectnum++; printf("%d connect ok\n", connectnum); return NULL;
}
int main(int argc, char ** argv) { if(argc < 2) { printf("Usage: testmem <host> [mode] [bind dn] [bind pwd]\n"); printf("mode: default: NORMAL; SSL;TLS\n"); return 0; } string mode="NORMAL"; if( argc > 2 ) mode = argv[2];
if( mode == "SSL" ) transMethod = LDAP_TRANS_SSL;
if( mode == "TLS" ) transMethod = LDAP_TRANS_TLS; host = argv[1];
if( argc > 4 ) { binddn = argv[3]; bindpwd = argv[4]; }
do { pthread_t instance_thread ; pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); int rc = pthread_create(&instance_thread, &attr, connectLDAP, NULL) ; pthread_attr_destroy(&attr); if (rc) { printf("Fail to create policy server instance thread\n") ; break; } sleep(1); }while(1); return 0; }
Ing. Pierangelo Masarati OpenLDAP Core Team
SysNet s.r.l. via Dossi, 8 - 27100 Pavia - ITALIA http://www.sys-net.it ----------------------------------- Office: +39 02 23998309 Mobile: +39 333 4963172 Fax: +39 0382 476497 Email: ando@sys-net.it -----------------------------------