Re: ldap_simple_bind blocks in SSL Mode when the DS is in hang state

Rich Megginson <[email protected]> Tue, 01 Sep 2009 11:13:53 -0600
Newsgroups gmane.comp.mozilla.devel.directory
Message-ID <[email protected]>
denish patel wrote:
> Thanks Rich,
> Let me clarify here.
> 
> The Application I am working on is a multi-threaded one
> & in that a single LDAP Handle is used by multiple thread s.
> 
> By thread safety, I mean that when this single LDAP Handle is used by
> multiple threads to fire queries/modify to the Directory Server,
> for which simple ldap functions such as ldap_search_ext / ldap_modify
> that reside in the Mozilla LDAP, then we wouldn't want to mix up the
> error/mutex/condition information between these threads.
> 
> It is specifically for this reason that we set the thread callback
> functions.
> 
> Do correct me if I am wrong.
> 
> Some questions here:
> 1) Don't I need to set the thread callback functions given my requirement?

No, you just need to use locking that is compatible with what mozldap is 
using.  The best way to do that is to get the functions used by mozldap. 
  If not using NSPR/NSS (not using IPv6 or TLS or SSL), the default 
thread libraries provided by the underlying operating system are used. 
For more details, see ldap/libraries/libldap/open.c.  If using prldap, 
prldap replaces these with their NSPR counterparts - see 
prldap_install_thread_functions() in 
ldap/libraries/libprldap/ldappr-threads.c

So I guess the best way to do it is to first call into the ldap library 
to see what function it's using:
LDAP *ld = ldap_init(...);
/* setup connection for TLS */

/* I need to lock the ld */
struct ldap_thread_fns ld_thr_fns;
ldap_get_option(ld, LDAP_OPT_THREAD_FN_PTRS, &ld_thr_fns);

if (mymutex == NULL) {
	mymutex = ld_thr_fns.ltf_mutex_alloc();
}
ld_thr_fns.ltf_mutex_lock(mymutex);

/* do something with ld */
/* unlock */
ld_thr_fns.ltf_mutex_unlock(mymutex);

You could probably just use pthreads or Windows thread primitives, or 
just use NSPR thread/mutex functions if you know your application will 
always need to support TLS/SSL.

Finally, if mozldap has been compiled with thread support, it will use 
Thread Local Storage to get/set the errno for a particular operation. 
For more information, see set_ld_error() and get_ld_error() in open.c - 
there are different implementations depending on the platform/threading 
model.

> 2) If an ssl connection is used & I fire a query then the will LDAP Handle
> used to fire the query
>     be thread-safe provided I am not setting the thread callback functions.

The LDAP handle (the LDAP *ld) will not be protected - that is, if one 
thread issues a query and another thread issues another operation using 
the same LDAP handle, the results may be wrong.  So you do need to 
protect access to the LDAP handle with a mutex.  However, as I have 
explained above, this does not mean you need to set the thread callback 
functions.

> 3) What would be the case if I am using an Open Connection.

What's an Open Connection?

> 
> Thanks,
> Denish
> 
> 
> 
> On Tue, Sep 1, 2009 at 8:26 PM, Rich Megginson <[email protected]>wrote:
> 
>> denish patel wrote:
>>
>>> Thanks for your reply Mark,
>>>
>>>  I am not sure about whether the prldap library uses
>>> NSPR to provide thread safety or not.
>>>
>> prldap uses NSPR to provide thread/mutex/condition variable functionality.
>>  prldap uses LDAP_OPT_THREAD_FN_PTRS to replace the default system thread
>> functions with NSPR.  I'm not sure what you mean by "provide thread safety".
>>
>>
>>> However, the LDAP C-SDK is not thread safe & for that
>>> purpose we are using the thread callback functions.
>>>
>> Only in a few cases is LDAP C SDK not thread safe.  What cases are you
>> talking about?
>>
>>
>>> Thanks,
>>> Denish
>>>
>>> On Tue, Sep 1, 2009 at 7:12 PM, Mark Smith <[email protected]> wrote:
>>>
>>>  denish patel wrote:
>>>>  Hi once again,
>>>>> Some more of my observations:
>>>>>
>>>>>  When LDAP_OPT_THREAD_FN_PTRS parameter is set the program goes into a
>>>>> loop.
>>>>> Debugging more it was found that the get_errno function is invoked by
>>>>> nsldapi_send_ber_message (Line No. 402 - request.c).
>>>>>
>>>>>  402.  int terrno = LDAP_GET_ERRNO( ld );
>>>>>  403.  if ( NSLDAPI_ERRNO_IO_INPROGRESS( terrno )) {
>>>>>  404.      if ( async ) {
>>>>>  405.         rc = -2;
>>>>>  406.         break;
>>>>>  407.      }
>>>>>  408.    } else {
>>>>>  409.        nsldapi_connection_lost_nolock( ld, sb );
>>>>>  410.        rc = -1;   /* fatal error */
>>>>>  411.        break;
>>>>>  412.   }
>>>>>
>>>>> It is from #402 that the get_errno function is invoked. This function
>>>>> returns 11 as mentioned in an earlier mail.
>>>>>
>>>>> The difference between the hanging & the non-hanging program lies here.
>>>>> When we do not set LDAP_OPT_THREAD_FN_PTRS, the value I see for terrno
>>>>> is
>>>>> 0,
>>>>> whereas it's value is 11 when the parameter has been set.
>>>>> ...
>>>>>
>>>>>  I am not 100% sure what is causing the problem you are experiencing (it
>>>> seems like your errno callback function is not returning the operating
>>>> system's errno value).
>>>>
>>>> I do not think this is well documented, but it is not a good idea to mix
>>>> together use of your own thread callback functions and the prldap library
>>>> (which is always used when you call the Mozilla LDAP C SDK SSL
>>>> functions).
>>>>  Do you really need to install your own thread callback functions?  The
>>>> prldap library uses NSPR to provide thread safety, and NSPR does a very
>>>> nice
>>>> job of hiding OS differences, etc.
>>>>
>>>> --
>>>> Mark Smith
>>>> Pearl Crescent
>>>> http://pearlcrescent.com/
>>>>
>>>>