Eventmachine 0.12.8

I am happy to announce the release of eventmachine 0.12.8. Gems
(including
binary builds for win32 and jruby) have been uploaded to rubyforge and
should
be available via gem install shortly.

This release contains almost 100 patches with numerous bug fixes,
improvements
and several new features. Highlights include:

  • Major code cleanups

    • converted all tabs to spaces in ruby source files
    • better documentation for all methods and classes
    • moved all protocol implementations to em/protocols/
    • split out eventmachine.rb to em/{connection,version,timers}.rb
    • removed several deprecated methods and classes
    • rake java:gem task to generate a binary jruby gem
  • Reactor fixes and improvements

    • worked around a kqueue bug in OSX causing nbytes>0 assertion
      failures
    • reduced the stack size of the epoll/kqueue reactors (this fixes a
      long-standing issue causing performance issues with ruby threads)
    • platforms that support it will use writev() to write data to the
      network, resulting in fewer memcpy()s
    • explicitly set non-blocking mode on attached sockets
    • allow read/write pipes to be watched using EM.attach
    • gettimeofday() is called only once per tick and used for timers,
      heartbeats and gCurrentLoopTime
  • Protocol improvements

    • added a simple DRb style ObjectProtocol, for communication using
      ruby
      objects (i.e. simple rpc server/clients:
      96699’s gists · GitHub)

      module RubyServer
      include EM::P::ObjectProtocol

      def receive_object obj
        send_object({'received object' => obj})
      end
      

      end

    • HttpClient2 callbacks are now passed in the response object

    • cleaner Postgres protocol

  • New APIs

    • EM.kqueue= and EM.epoll= can be used to toggle kqueue/epoll

    • EM.threadpool_size= sets the size of the EM.defer threadpool

    • EM.ssl? will check if the reactor was built with ssl support

    • EM.schedule{} helper runs a block in the main reactor thread

    • EM.reactor_thread? checks if the current thread is the reactor
      thread

    • EM.system now returns the new process’ pid and can take multiple
      args

      pid = EM.system(‘sleep’, 1000){ |out, status|
      # pid == status.pid
      # 15 == status.termsig
      p [pid, out, status]
      }
      Process.kill 15, pid

    • EM::Channel allows for in-reactor publish/subscribe

      chan = EM::Channel.new
      sid = chan.subscribe{ |msg|
      p [:got, msg]
      }

      chan.push(‘hello’)
      chan.push(‘world’)
      chan.unsubscribe(sid)

    • EM::Queue provides a simple queue with asynchronous pops

      q = EM::Queue.new
      q.push(1, 2)
      3.times do
      q.pop{ |num| p [:got, num] }
      end
      q.push(3)

    • EM.watch_file uses kqueue on OSX or inotify on linux to watch a
      file,
      triggering events when the file is modified, moved or deleted

      module EtcPasswd
      def file_modified
      STDERR.puts ‘WARNING /etc/passwd WAS MODIFIED’
      end
      end

      EM.run{
      EM.watch_file ‘/etc/passwd’, EtcPasswd
      }

    • EM.watch_process will watch a pid, triggering events when the
      process
      forks or dies (note this currently only works with kqueue)

      module DaemonWatcher
      def process_exited
      STDERR.puts ‘WARNING your daemon has died’
      end
      end

      EM.kqueue = true
      EM.run{
      EM.watch_process(some_daemon_pid, DaemonWatcher)
      }

    • EM.enable_proxy will natively proxy data between two connections,
      without
      the overhead of converting incoming data to ruby strings

    • EM::Connection#comm_inactivity_timeout= now takes a float

    • EM.heartbeat_interval= changes how often sockets are checked
      for inactivity

    • EM.bind_connect binds an outgoing socket to a specific local
      ip/port

    • EM::Connection#ssl_verify_peer callback allows servers to verify
      client
      ssl certificates (use start_tls(:verify_peer => true))

  • Ruby API fixes

    • EM.add_timer() can take a number of seconds as a string
    • EM.open_datagram_socket() correctly handles string ports
    • EM::Connection#send_data will now call .to_s on its argument
    • the EM.next_tick{} queue is cleaned up on reactor shutdown (this
      fixes an
      issue in AMQP when connecting and disconnecting multiple times)
    • fixed potential memory leak in EM.cancel_timer

At this time, there are a few known issues which will be fixed for
0.12.10,
along with a couple new features that are in the works:

  • EM.current_time is broken

    EM.current_time returns random time objects due to a change to
    gCurrentLoopTime in the reactor. This has been fixed in the latest
    git master branch.

  • ruby 1.9 win32 support

    EM works with 1.9 on linux, but still fails to build on win32. The
    next release will include an official win32 ruby 1.9 binary gem.

  • EM::Iterator

    Looping over large arrays blocks the reactor and introduces
    latency.
    0.12.10 will include EM::Iterator to spread out iterations over
    multiple
    reactor ticks.

  • jruby patches

    Interest in the jruby reactor has been increasing, and there are
    several
    patches in the works by Hemant ‘gnufied’ Kumar. 0.12.8 works with
    jruby,
    but is missing several features that are available in the c++
    reactor.

  • require ‘openssl’ issues

    Custom ruby builds on OSX will segfault if you require ‘openssl’
    after
    eventmachine. To work around this issue, simply:

    require 'openssl'
    require 'eventmachine'
    
  • async dns lookups

    There are currently a few ways of doing async dns lookups with EM,
    using either em-dns, em-asyncns or dnsruby. The next release will
    include an async dns implementation which will be used by default.

  • exceptions in post_init/initialize are silently swallowed

    Exceptions raised in your handler’s post_init or initialize
    methods
    are silently swallowed and cause an ConnectionUnbound error to
    surface
    later on with a confusing error message. If you’re experiencing
    issues,
    use an error handler to catch the original exception:

    EM.error_handler{ |e|
      puts e
      puts e.backtrace.join("\n  ")
    }
    
  • process watching on linux using netlink

    EM.watch_process is currently only implemented for kqueue. The
    next
    release will add support for linux using the netlink code from
    God.

  • better, more stable test suite

    The current test suite is very unstable and does not test the pure
    ruby,
    jruby, kqueue or epoll reactors. We plan on overhauling the suite
    to
    provide better test coverage and ensure stability of the different
    reactors and platforms.

Special thanks to the following people for making this release possible:

  • Bob Potter
  • Eugene Pimenov
  • Jake ‘yakischloba’ Douglas
  • Joern Barthel
  • James ‘raggi’ Tucker
  • coderrr

The rdoc has been updated and is available at
http://eventmachine.rubyforge.org

Aman