Hi all, I'm using RubyLDAP all over the place in my Rails app. I'm curious, though, if I'm not specifically unbinding in certain places, are the connections kept open? Also, assuming I've subclassed LDAP::Conn to provide a class specific to our LDAP here, will this leave a bound connection hanging? def check_password(userdn, password) return OurLDAP.new.bind.compare(userdn, "userpassword", password) end Basically, I just want to check and make sure the password is valid. OurLDAP.new.bind binds as a user that can compare on that attribute. Am I leaving a connection open? Thanks! Sean
on 2006-05-05 23:38
on 2006-05-06 04:21
I'm assuming you're using the Ruby-LDAP library that wraps up the native client libraries. These libraries have behavior with respect to the network that is hard to predict. In particular, unbinding doesn't necessary drop the network connection. I'm not knowledgeable enough to say whether Ruby's GC interacts with this, although that's an interesting possibility. Another really weird one is if you should have an unsuccessful binding: on Linux, this will often cause the native LDAP library to leak a TCP connection, even if you properly destruct the library-level object. Very frustrating, I know about that one from very painful experience. I took a shot at writing a pure-Ruby LDAP client that would have much better-defined semantics with regard to the network, Try it, it's called ruby-net-ldap on Rubyforge. If you do try it, please let me know if it works any better for you.
on 2006-05-15 19:11
Sean Hussey wrote: > I'm using RubyLDAP all over the place in my Rails app. I'm curious, > though, if I'm not specifically unbinding in certain places, are the > connections kept open? The connection is kept open until the connection object is garbage collected, if you call the binding method without a block. However, if you call the binding method with a block, the connection is closed using Conn#unbind at the end of the block. Also, Ruby/LDAP wraps up the native LDAP library as Francis wrote. So behavior of the binding and unbinding methods rely on C API called ldap_bind() and ldap_unbind() defined in RFC1823. In particular, ldap_unbind() is defined to close the connection as follows. 4.3. Closing the connection ldap_unbind() is used to unbind from the directory and close the connection. int ldap_unbind( LDAP *ld );
on 2006-05-16 22:58
That bit about the block is a huge and powerful concept. I learned about the general concept this weekend at the Rails studio and wondered if it applied to RubyLDAP. Thanks for pre-answering my question! I think I'll try to rewrite pieces of the app to apply that method. Thanks! Sean
on 2006-05-17 00:00
Sean, if you have evidence that you are leaking a connection (perhaps from /proc/pid/fd), then you should consider the possibility that the underlying native-LDAP library is leaking the connection, regardless of Ruby's behavior. I'm quite sure (from experience) that this happens with certain versions of the openldap client when you bind unsuccessfully, and it happens even if you do the right thing and call unbind (or have Ruby call it for you at the end of the block).
on 2006-05-17 02:37
One possibility may have been related to network configuration changes that were made (mostly dealing with timeouts on our firewall). Those changes were reversed yesterday (they were causing SMTP and LDAP errors) and, lo-and-behold, the issues I was having with my app are gone. I'm not sure if they're related, but it's mighty coincidental that my app had problems around the time the change was made, and then recovered when the change was reversed. I wonder if my LDAP connections weren't being GC'ed quickly enough to counteract the firewall timeout.