It seems the dichotomy between libldap and libldap_r is a relic from the bad old days of dcethreads / cmathreads when linking a threaded library into an otherwise non-threaded program would cause all sorts of strange and wonderful failures. Unless anyone knows of any current platform where this is unsafe, I think it's time we dropped this distinction, and just use libldap_r (until we get to writing a completely new C API).
libldap_r is still missing some thread-specific features though - we should wrap all library initialization in a pthread_once() call, and we should be using thread-specific data for the LDAP* errno value.
Howard Chu wrote:
It seems the dichotomy between libldap and libldap_r is a relic from the bad old days of dcethreads / cmathreads when linking a threaded library into an otherwise non-threaded program would cause all sorts of strange and wonderful failures. Unless anyone knows of any current platform where this is unsafe, I think it's time we dropped this distinction, and just use libldap_r (until we get to writing a completely new C API).
libldap_r is still missing some thread-specific features though - we should wrap all library initialization in a pthread_once() call, and we should be using thread-specific data for the LDAP* errno value.
It should be detectable whether the new libldap behaves like former libldap_r.
In python-ldap all calls into libldap or libldap_r are serialized by locks in the Python wrapper part. The locking is different if python-ldap was built against libldap_r (locks are per connection then). So a clear distinction with LDAP_API_VERSION would be appreciated.
Ciao, Michael.
Howard Chu hyc@symas.com writes:
It seems the dichotomy between libldap and libldap_r is a relic from the bad old days of dcethreads / cmathreads when linking a threaded library into an otherwise non-threaded program would cause all sorts of strange and wonderful failures. Unless anyone knows of any current platform where this is unsafe, I think it's time we dropped this distinction, and just use libldap_r (until we get to writing a completely new C API).
That would be *great*. I'm wholeheartedly in favor.
On Thu, 24 Sep 2009, Howard Chu wrote:
It seems the dichotomy between libldap and libldap_r is a relic from the bad old days of dcethreads / cmathreads when linking a threaded library into an otherwise non-threaded program would cause all sorts of strange and wonderful failures.
Hmm, my impression from reading the source was that it was more about use models, where libldap is appropriate when any given LDAP handle would not be accessed concurrently by multiple threads and libldap_r is appropriate when a given LDAP handle may be serviced/used concurrently by multiple threads.
Indeed, my impression from reading the ldap_r bits was that processing of replies wasn't ideal when threads were asking for specific replies, as asking for a given reply blocked *all* other ldap_result() calls on that handle until that specific reply was received.
(To hopefully make clear: thread1 thread2 ldap_result(h, msg_A) ldap_result(h, msg_B) receive msg_B <still blocked...> receive msg_A return from ldap_result return from ldap_result )
For an application design where that would be a problem, it's better off with independent handles or its own demultiplexor...at which point all those locks inside the LDAP handle are just overhead. At Sendmail, several of our commercial programs use a library to manage reconnections, resubmitting queries after failover between servers, etc. They all just link against libldap** and not libldap_r, despite having multiple threads concurrently in the LDAP code, because those extra locks would be wasted given the design.
** compiled with whatever it takes to get a thread-safe errno, etc
..
libldap_r is still missing some thread-specific features though - we should wrap all library initialization in a pthread_once() call, and we should be using thread-specific data for the LDAP* errno value.
Without knowing what usage models this is supposed to address or provide, I don't see the benefit.
Philip Guenther
Philip Guenther wrote:
On Thu, 24 Sep 2009, Howard Chu wrote:
It seems the dichotomy between libldap and libldap_r is a relic from the bad old days of dcethreads / cmathreads when linking a threaded library into an otherwise non-threaded program would cause all sorts of strange and wonderful failures.
Hmm, my impression from reading the source was that it was more about use models, where libldap is appropriate when any given LDAP handle would not be accessed concurrently by multiple threads and libldap_r is appropriate when a given LDAP handle may be serviced/used concurrently by multiple threads.
libldap_r was added out of necessity for the latter case, yes. Prior to that there was basically no consideration for threading at all.
Indeed, my impression from reading the ldap_r bits was that processing of replies wasn't ideal when threads were asking for specific replies, as asking for a given reply blocked *all* other ldap_result() calls on that handle until that specific reply was received.
(To hopefully make clear: thread1 thread2 ldap_result(h, msg_A) ldap_result(h, msg_B) receive msg_B <still blocked...> receive msg_A return from ldap_result return from ldap_result )
Not entirely true. Threads only block in ldap_int_select(); it's undefined which thread will wake up first when select has data ready. The above scenario may occur sometimes, and does not occur other times. We may consider it a bug that the behavior is non-deterministic, but that's a separate issue.
libldap_r is still missing some thread-specific features though - we should wrap all library initialization in a pthread_once() call, and we should be using thread-specific data for the LDAP* errno value.
Without knowing what usage models this is supposed to address or provide, I don't see the benefit.
The benefit is decreasing the number of libraries that need to be maintained, and eliminating the conflict when code linked against one library is dynamically loaded into a process that was already linked with the other.
Howard Chu hyc@symas.com writes:
The benefit is decreasing the number of libraries that need to be maintained, and eliminating the conflict when code linked against one library is dynamically loaded into a process that was already linked with the other.
Indeed, Debian has been trying to use only libldap_r for some time because of the latter issue, and we would love to throw out the way we're handling that in favor of adopting a maintained and supported build configuration.