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