Joel VanderWerf
3/31/2006 9:38:00 PM
Dominik Werder wrote:
> Hello,
>
> I found the bug: In the client code the variable "socket" was already
> known to the interpreter, but anyway not in the same scope, so every
> thread overwrote the socket and in the end all used the same connection..
>
> I didn't know that
>
> if false
> yo = 123
> else
> puts yo.class.name
> end
>
> would output "NilClass"..
I'm getting more and more defensive about this kind of bug. I usually
just do
Thread.new(...) { |...| some_method(...)}
and then I can code some_method without worrying about local variable
sharing.
Another example is when threads are created in a loop. Even if the
thread code is very small, local vars with shared binding can be
devastating:
a = []
i = 0
(0...100).map do
Thread.new {sleep 0.001; a << i}
i += 1
end
sleep 1
p a.uniq.size
Output is unpredictable, 74, 86, etc. (YMMV)
Obviously, this could be solved by making i local to the block, or
passing it to Thread.new. Without the sleep 0.001, I don't seem to get
this behavior (the output is 100), but I wouldn't rely on that: the ruby
thread scheduler could still reasonably schedule threads so that two or
more of them saw the same value of i. So it's still best to pass
arguments to Thread.new.
--
vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407