From: Sean O'Halpin Date: 2013-01-04T22:44:26+09:00 Subject: Re: GServer in Ruby 2.0.0 On Tue, Jan 1, 2013 at 4:20 PM, Joe Leo 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