At Tue, 23 Jul 2002 03:25:10 +0900,
Mike Hall wrote:

> Summary: do a couple file-controls, setup a signal handler,
> wait for a signal to occur.
> 
> This works OK in a single threaded script,
> but it makes all the threads stop, when I use it
> inside a thread.

Though I'm not sure of what you'd like to do, the following sketchs
how to raise an exception from specified thread when a signal is trapped.  

hope this helps,

#---------------------------------------------------------------------- begin module Signal # backward compatibility for Ruby 1.7 feature unless self.respond_to?(:list) LIST = { # obtained on freebsd4 "HUP" => 1, "INT" => 2, "QUIT" => 3, "ILL" => 4, "TRAP" => 5, "ABRT" => 6, "IOT" => 6, "EMT" => 7, "FPE" => 8, "KILL" => 9, "BUS" => 10, "SEGV" => 11, "SYS" => 12, "PIPE" => 13, "ALRM" => 14, "TERM" => 15, "URG" => 16, "STOP" => 17, "TSTP" => 18, "CONT" => 19, "CHLD" => 20, "CLD" => 20, "TTIN" => 21, "TTOU" => 22, "IO" => 23, "XCPU" => 24, "XFSZ" => 25, "VTALRM" => 26, "PROF" => 27, "WINCH" => 28, "INFO" => 29, "USR1" => 30, "USR2" => 31 }.freeze def self.list() LIST end end end class UnhundledThreadedSignal < Exception; end class Thread Signal_to_Thread = {} def raise_by_signal(signal, exception = RuntimeError, opt = "") signo = Signal.list[signal] Signal_to_Thread[signo] = [self, exception.new(opt)] ::Kernel::trap(signal) do |s| t, e = Signal_to_Thread.delete(s) t ? t.raise(e) : ::Kernel::raise(UnhundledThreadedSignal) end end end class Sig1 < StandardError; end class Sig2 < StandardError; end child = fork do # sandbox trap("HUP"){ exit } tg = ThreadGroup.new for i in 0..9 Thread.start(i) do |n| ct = Thread.current tg.add(ct) case n when 1 loop do begin ct.raise_by_signal("USR1", Sig1, "USR1 signaled") STDERR.print("\r#{n} ") sleep rand rescue Sig1 => e STDERR.printf("\r%s\n", [n, e].inspect) end end when 2 loop do begin ct.raise_by_signal("USR2", Sig2, "USR2 signaled") STDERR.print("\r#{n} ") sleep rand rescue Sig2 => e STDERR.printf("\r%s\n", [n, e].inspect) end end else loop do STDERR.print("\r#{n} ") sleep rand end end end end tg.list.each{|i| i.join} end # parent sleep 1 # waiting setup of child begin 5.times do Process.kill("USR1", child) sleep(rand*2) Process.kill("USR2", child) end ensure Process.kill("HUP", child) Process.wait end #------------------------------------------------------------------------ end