bearded / ruby-ldap

Ruby/LDAP is an extension library for Ruby. It provides the interface to some LDAP libraries (e.g. OpenLDAP, Netscape SDK and Active Directory). The common API for application development is described in RFC1823 and is supported by Ruby/LDAP.
http://rubyforge.org/projects/ruby-ldap/
Other
66 stars 34 forks source link

GIL is not released when calling blocking IO functions from C #37

Open jjmason opened 8 years ago

jjmason commented 8 years ago

C functions like ldap_open block until a connection is opened. If an upstream LDAP is bogged down, or someone attempts to connect to a server that doesn't support LDAP and lets the connection time out, all other ruby threads are blocked until the ldap_open call returns. Here is some code to demonstrate this:

#!/usr/bin/env ruby
require 'ldap'

# Start a thread that prints 'beep!' every second.
beeper = Thread.new do 
  loop do
    puts "beep!"
    sleep 1
  end
end

# sleep the main thread so the beeper can get a few messages out
sleep 3

# Google.com hangs for a rather long time when we try to open
# a connection on port 389.

puts "about to connect to google.com:389..."

conn = LDAP::Conn.open 'google.com', 389

puts "connected???" # looks like we've hacked google!

Expected result: The beeper thread will continue to print "beep!" every second while the ldap connection is being opened.
Actual result: The beeper thread stops until the call to LDAP::Conn.open finishes.

I encountered this issue on a project for work where users can perform certain LDAP actions through a web user interface. Because the project uses a threaded webserver (Puma), a connection attempt that takes a while will block all other requests to the server from being processed. While switching to a multi-process webserver is an obvious solution, it would be better for this library to perform the IO with the GIL released so that other threads can make progress, which is the behavior of other blocking native IO in ruby.

bearded commented 8 years ago

Hello @jjmason, could you please try a version from branch gh-37 ?