[MacRuby-devel] Concurrency bug in ControlTower

Charles Oliver Nutter headius at headius.com
Wed Jan 26 00:49:49 PST 2011


On Mon, Jan 24, 2011 at 11:13 AM, Joshua Ballanco <jballanc at gmail.com> wrote:
> Regarding the potential bug...well...where to begin? So, yes, MacRuby blocks
> have the same semantics as regular Ruby blocks, *except* when they are
> dispatched through GCD. In that case, ivars are shared, but local variable
> get copied. I'm sure Laurent can explain why better than I, but it has to do
> with the semantics of libdispatch and the uncertainty inherent in when a
> dispatched block or function will execute (i.e. if local variables were not
> copied during dispatch, they might go out of scope and be collected before
> GCD ever gets around to running the code).

Wow, that's very surprising. I'm not sure I agree with bending Ruby
semantics so drastically, even to help concurrency. Or at least, I'd
expect other threaded scenarios to be consistent:

~ ➔ ruby -ve "a = 0; Thread.new { a += 1 }.join; p a"
MacRuby 0.8 (ruby 1.9.2) [universal-darwin10.0, x86_64]
1

~ ➔ ruby -ve "a = 0; q = Dispatch::Queue.concurrent; q.sync {a += 1}; p a"
MacRuby 0.8 (ruby 1.9.2) [universal-darwin10.0, x86_64]
0

The implicitness in being able to mutate the surrounding scope is
certainly problematic. This is one reason Java's anonymous inner
classes require that referenced variables be declared final...to
indicate they can't be mutated by the body of the anonymous inner
class's methods.

The result is that people end up using one-element arrays and the
like, but people find ways around anything.

So I suppose this applies to anything in the surrounding scope,
including visibility, $~, and so on?

> To illustrate how this impacts async semantics wrt ruby, here's a sample
> done with MacRuby/GCD and canonical Ruby:

I'll see how this might be implemented in JRuby.

> In other words, not a bug in MacRuby...also, this code is scheduled for a
> rewrite that will turn it into a bit more of a continuation-passing style of
> handling the connections. I don't think tap is really the solution we are
> looking for here, since after dispatching, the main #accept loop doesn't
> really care about that connection (other than that, at some point, it is
> responsibly closed).

tap would be a clean way to explicitly isolate each loop's
environment, if you weren't already doing that.

- Charlie


More information about the MacRuby-devel mailing list