On Tue, Jan 1, 2013 at 4:20 PM, Joe Leo <joseph.leo3 / gmail.com> wrote:
> I'm working on updating a gem to be compatible with Ruby 2.0 and am
> currently using Ruby 2.0.0-preview2. I'm running into trouble with a
> class which inherits from GServer and I think it's related to this bug and
> subsequent patch. Please look at the gist:
> https://gist.github.com/4424479
>
> Using Ruby <= 1.9.3, when sending an interrupt signal this code would
> exit cleanly. Using Ruby 2.0, an exception is thrown on launcher.stop:
>
> ~/.rvm/rubies/ruby-2.0.0-preview2/lib/ruby/2.0.0/gserver.rb:116:in
> `synchronize': can't be called from trap context (ThreadError)
>     from
> ~/.rvm/rubies/ruby-2.0.0-preview2/lib/ruby/2.0.0/gserver.rb:116:in
> `stop'
>

I can confirm this is new behaviour in 2.0.0-preview2 - it also
happens when you use Queue#enq from within a trap handler (which is an
issue for me unfortunately).

You could use a variant of the self-pipe trick to signal a thread as
in the example below. Regards, Sean.

# CODE

require "gserver"

# example server
class MyServer < GServer
  def initialize(port=10001, *args)
    super(port, *args)
  end
  def serve(io)
    io.puts(Time.now.to_s)
  end
end

class Launcher
  def initialize(servers)
    @servers = servers
  end

  def start
    @servers.each { |server| server.start }
  end

  def join
    @servers.each { |server| server.join }
  end

  def stop
    @servers.each { |server| server.stop }
  end
end

servers = [MyServer.new]
launcher = Launcher.new(servers)

# create self-pipe
p_read, p_write = IO.pipe

Thread.start(launcher, p_read) do |l, pr|
  pr.read # blocks until write end closed
  pr.close
  l.stop
  exit
end

launcher.start
trap("SIGINT") { p_write.close } # close pipe to signal thread
launcher.join