Skip to content

Thread safety of plugins and gems

randomecho edited this page Aug 10, 2012 · 4 revisions

Introduction

Rails 2.2 is just around the corner and one of the major new features is thread-safety of the Rails core.

Pratik Naik and Charles Nutter have done a great job of explaining what this means and why you could benefit from it (or not).

More technically speaking it’s about the ability to handle multiple requests concurrently in a thread-safe manner (you could say Rails always has been thread-safe by enabling just one concurrent request per Ruby instance).

Any shared resource, which is not read-only, must be treated specially in a multi-threaded environment. What exactly are shared resources in the case of Rails? Luckily each request gets its own set of controller and view instances in Rails. So usually working with instance-related data (like @ variables) is already thread-safe (since one request always maps to one thread).

The situation is different with plugins and gems. They often provide some more sophisticated and lower-level functionality and for instance make heavy use of class variables.

So I’ve started looking at the code the plugins and gems, which I typically use for my projects, to see if they can be used with multi-threading turned on. One thing I found out is that it’s easy to find a smoking gun and to flag code as being not thread-safe. But it’s much harder to declare a gem to be safe. Actually you have to look thoroughly at all the code.

So this is just a starting point. I’ve only searched for usage of class variables for now. Maybe we can establish this page to collect information about all sorts of plugins and gems and track the progress they make. Please contribute and help making the complete Rails eco-system threadsafe. Any corrections, reports about plugins or maybe ideas for a more systematic approach. Any sort of feedback welcome!

Plugins / Gems

  • youtube_g

class Format
  @@formats = Hash.new

  def initialize(format_code, name)
    @format_code = format_code
    @name = name

    @@formats[format_code] = self          
  end

Potentially not thread-safe.

  • attachment_fu / s3_backend:

  def self.hostname
    @hostname ||= s3_config[:server] || AWS::S3::DEFAULT_HOST
  end

Potentially not thread-safe.

  • new relic:

  def Agent.instance
    @@agent ||= Agent.new

    @@agent
  end      

Potentially not thread-safe.

  • htpasswd

  def register(klass)
    @@entries[klass.name.demodulize.classify] = klass
  end

Potentially not thread-safe.

  • ActiveMessaging:

Not threadsafe: “this is not thread safe; a13g is not in any way guaranteed to be thread
safe. It was not written with this in mind.”

Check out the Threadsafety post

  • mislav-will_paginate 2.3.6

seems OK so far.