I've been away from this list for a while, so I don't know what the current
thinking is behind the scoping rules for block-local variables, and whether
they're likely to be changed.

But I've just been bitten by this. Have a look at the following code, and
see if you can see what's wrong with it just by inspection. It accepts TCP
connections on a socket, and starts a server in a thread for each one. It's
a nice pattern for TCP servers.

-----------------------------------------------------------------------
require 'socket'
module MyModule
  def run
    puts "Hello, world!" 
    sleep 10
    puts "Goodbye"
    # ... could do other stuff
  end
end

port = (ARGV[0] || 7000).to_i
bind = (ARGV[1] || '0.0.0.0')
server = TCPserver.new(bind, port)

# For each connection, add our 'run' method to the I/O object and run it
# in its own thread

while (session = server.accept)
  session.extend MyModule
  Thread.new do
    begin
      session.run
    rescue Exception => e
      STDERR.puts "Caught exception: #{e}\n\t#{e.backtrace.join("\n\t")}"
    ensure
      session.close
    end
  end
end
-----------------------------------------------------------------------

To demonstrate the problem: run it in one window, and then in two further
windows type "telnet localhost 7000" in each, less than 10 seconds apart.
Watch the second one fail, and also see an exception reported by the server.

After quite a bit of head-scratching, and boiling my server down to the
simple code shown above, I managed to work out what was wrong and fix it.

However, I wonder if the language could have helped me more here? "ruby -w"
didn't spot any problem (although perhaps it would be hard for it to do so).

I think this is a type of problem which unit testing is unlikely to find,
unless you are specifically aware of it.

Regards,

Brian.


v




v




v




v




v




The fix:
-----------------------------------------------------------------------
...
while (s = server.accept)
  s.extend MyModule
  Thread.new(s) do |session|
    begin
...