From: Joel VanderWerf Date: 2006-02-19T09:00:25+09:00 Subject: Re: Thread#stop Daniel Sheppard wrote: > The following probably contains world-destroying race-conditions, but it > roughly works. Making it work properly is left as an exercise for the > reader. > > > $stoppable = [] > $stop_all = false > > def stop_all > $stop_all = true > end > > def start_all > $stop_all = false > $stoppable.each {|t| p "waking #{t}"; t.wakeup} > end > > set_trace_func proc { |event, file, line, id, binding, classname| > if $stop_all && $stoppable.include?(Thread.current) > p "#{Thread.current} stopping" > Thread.stop > p "#{Thread.current} restarted" > end > } > > $stoppable << Thread.new { > while sleep 1 > p "child is running" > end > } > > p "started" > sleep 5 > p "stopping all" > stop_all > sleep 5 > p "starting all" > start_all > sleep 5 > p "exiting" > On second thought, this is actually just what I need, with a small modification: only call set_trace_func when the request to stop comes in, and then call set_trace_func(nil) when threads are restarted. For example: th = Thread.new do loop do sleep 0.1 puts "alive!" end end sleep 0.3 puts "stopping" stopper = proc {|event, file, line, id, binding, classname| Thread.stop if Thread.current == th } set_trace_func stopper sleep 1 puts "starting" set_trace_func nil th.wakeup sleep 0.3 The output is: alive! alive! stopping starting alive! alive! alive! (There's about a 1 sec delay between the "stopping" and "starting" lines, as desired.) So, thanks for the suggestion, Daniel. I just didn't consider it closely enough before, because I was scared away by set_trace_func. -- vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407