[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Re: Thread#stop

Daniel Sheppard

2/15/2006 11:40:00 PM

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"


3 Answers

Joel VanderWerf

2/15/2006 11:55:00 PM

0

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.

Nice, but I think set_trace_func is going to kill my app. Thanks anyway,
though.

--
vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407


Joel VanderWerf

2/19/2006

0

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


Joel VanderWerf

2/19/2006 12:18:00 AM

0


And with a little extra work, one can use this to approximate
Thread#backtrace as well as Thread#stop (neither of which exist):

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|
if Thread.current == th
puts caller.join("\n from ")
Thread.stop
end
}
set_trace_func stopper

sleep 1

puts "starting"
set_trace_func nil
th.wakeup

sleep 0.3


alive!
alive!
stopping
thread-stop.rb:6
from thread-stop.rb:6
from thread-stop.rb:4
from thread-stop.rb:3
starting
alive!
alive!
alive!



(This is only approximate because the thread isn't stopped until after
the interpreter finishes whatever current ruby primitive is evaluating,
but it's good enough for my purposes.)

--
vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407