Non-Threaded Timeout?

Actually, after taking a closer look at the timeout method distributed
with Ruby, I don’t understand why it doesn’t work for me… can anyone
explain that to me? To me, it looks like it’s doing exactly the same
thing Ara suggested doing with signal traps, but with threads instead.
So how come it doesn’t work?


Thanks!
Bryan

On Aug 11, 2008, at 4:48 PM, Bryan R. wrote:

Actually, after taking a closer look at the timeout method distributed
with Ruby, I don’t understand why it doesn’t work for me… can anyone
explain that to me? To me, it looks like it’s doing exactly the same
thing Ara suggested doing with signal traps, but with threads instead.
So how come it doesn’t work?

with ruby, only one thread runs at once because they are green
trheads. so if you do something that blocks your entire process, like
and OLE call, you block all threads. this is mainly a windows issue.

a @ http://codeforpeople.com/

Got it. Thanks for taking the time to explain it to me.


Bryan

Hi Ara,

I agree that the principal of the idea is about the only one to pursue
on Windows. I tried the following code:

def timeout seconds, key, &block
pid = Process.pid
signaler = IO.popen “ruby -e’sleep #{ seconds };
Process.kill(:#{key}.to_s, #{ pid }) rescue nil’”
handler = Signal.trap(key){ raise ‘timed out…’ }
begin
block.call
ensure
Process.kill key, signaler.pid rescue nil
Signal.trap(key, handler)
end
end

Signal.list.keys.each do |key|
puts key
unless key == ‘KILL’
timeout(2, key) { p ‘works’ }
timeout(1, key) { sleep 2; p ‘does not work’ }
end
end

and it produced the following output:

ruby timeout_test.rb
TERM
“works”
“does not work”
SEGV
“works”
“does not work”
KILL
EXIT
“works”
“does not work”
INT
“works”
“does not work”
FPE
“works”
“does not work”
ABRT
“works”
“does not work”
ILL
“works”
“does not work”
Exit code: 0


Thanks!
Bryan

Ara Howard wrote:

did you try the ‘INT’ signal? there are only a few signals supports
in windows between process and i forget which is which. in any case,
even if that exact code will not work the principle will: that of
setting up an external process to do something to your (potentially
blocked) process. in fact it’s the only way out when you consider
ruby’s thread impl.

Alright, so here’s what I’ve now been trying:

If I kill the external application that I’m using the OLE/COM
interface to talk to while my Ruby program is running, I get a
WIN32OLERuntimeError in my Ruby program. Thus, since
Process.kill(‘KILL’, ) does seem to work on Windows (I did test
this), I figured I could make my timeout method look like this:

def timeout(sec, pid)
begin
watchdog = IO.popen “ruby -e ‘sleep(#{sec});
Process.kill(:KILL.to_s, #{pid}) rescue nil’”
yield
ensure
Process.kill(‘KILL’, watchdog.pid) rescue nil
end
end

and I could call it like this:

@sim = WIN32OLE.new ‘PwrWorld.SimulatorAuto’

begin
timeout(20, @sim.ProcessID) do
@sim.RunScriptCommand(‘SolvePrimalLP()’)
end
rescue WIN32OLERuntimeError

rescue myself from the external application hanging up… i.e.

reinitialize @sim
end

However, it seems as though when creating the watchdog in the timeout
method IO.popen sometimes blocks execution. I can’t tell if it’s due
to the external (OLE) application blocking or something else. If I
don’t use the timeout method the OLE application blocks at a different
time in the simulation, so I’m thinking it’s not due to the OLE
application blocking…

Any ideas?!

On Aug 12, 2008, at 12:38 PM, Bryan R. wrote:

and I could call it like this:
end

However, it seems as though when creating the watchdog in the timeout
method IO.popen sometimes blocks execution. I can’t tell if it’s due
to the external (OLE) application blocking or something else. If I
don’t use the timeout method the OLE application blocks at a different
time in the simulation, so I’m thinking it’s not due to the OLE
application blocking…

can you prove that it’s popen blocking? seems very strange…

a @ http://codeforpeople.com/

At this point I can’t say I’ve proven it… about the only thing I’ve
done is stick logging commands around the creation of the watchdog.
The log statement before gets logged, the one after does not.
However, I’m not exactly sure how log4r works either so who knows if
the OLE stuff is jacking with it also! :confused:

From: “ara.t.howard” [email protected]

can you prove that it’s popen blocking? seems very strange…
I’m just jumping into the middle of the thread, so apologies if
I’ve missed something; but …

popen blocks ALL ruby threads on windows. This has been the bane
of my existence for the past eight years. :slight_smile:

The problem is due to Microsoft’s venerable design strategy: You are
lost in a twisty little maze of API’s, all incompatible.

On Windows, the “file handle” returned by popen is not a “socket”,
and therefore is incompatible with “select”.

/me raises a cup of hemlock in toast to Redmond

Note: Now that 1.9 ruby uses native threads, it should be possible
to implement a nonblocking popen. However, last time I tested 1.9
for this behavior, it still blocked. (This was several months ago.)

Regards,

Bill

Hi Bill,

Thanks for the reply. I hate Windows. :slight_smile:

I did a few tests (all-be-it I came up with the tests, so that might
be the problem) and it does seem like IO.popen is blocking…

IO.popen “ruby -e ‘sleep(20); STDERR.puts “Popped!”’”
sleep(10)
puts “Hello”
sleep(15)
puts “Hi”

Output was:
Popped!
Hello
Hi

I CAN’T CATCH A BREAK ANYWHERE!!! Argh… this is why I don’t
develop on Windows! :frowning:

On Aug 12, 2008, at 4:34 PM, Bryan R. wrote:

sleep(15)
puts “Hi”

Output was:
Popped!
Hello
Hi

I CAN’T CATCH A BREAK ANYWHERE!!! Argh… this is why I don’t
develop on Windows! :frowning:

see if you can sort of get it going with system - i know you can
cancel it, but you might be able to work around that later…

a @ http://codeforpeople.com/