[MacRuby-devel] Concurrency bug in ControlTower

Charles Oliver Nutter headius at headius.com
Fri Jan 21 23:14:19 PST 2011


Apologies reporting this here; I'm not sure where I should report bugs
in ControlTower.

I believe there's a bug in ControlTower around line 34:

    def open
      @status = :open
      while (@status == :open)
        connection = @socket.accept # << here

        @request_queue.async(@request_group) do

The "connection" local variable is used in the async block below to
parse the request and send the response. Unless MacRuby's blocks
behave differently than regular Ruby, this variable is shared across
all activations of that block. As a result, it's possible that two
concurrent requests will end up using each others' connection, and
usually just blowing up as a result.

The fix I've come up with is to wrap the @request_queue.async call in
a tap call:

    def open
      @status = :open
      while (@status == :open)
        conn = @socket.accept

        conn.tap do |connection|
          @request_queue.async(@request_group) do

Since async can't accept any explicitly-passed state, this seems like
the safest way to ensure the connection reference is not shared by
separate invocations. I'm not sure if it's possible in GCD, but having
async take an optional argument with explicitly-passed state might
also be a good way to fix this.

- Charlie


More information about the MacRuby-devel mailing list