Non-Threaded Timeout?

  • Thread starter Bryan Richardson
  • Start date
B

Bryan Richardson

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"
 
B

Bryan Richardson

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?
 
A

ara.t.howard

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/
 
B

Bryan Richardson

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', <pid>) 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?!
 
A

ara.t.howard

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...



can you prove that it's popen blocking? seems very strange...

a @ http://codeforpeople.com/
 
B

Bryan Richardson

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! :/
 
B

Bill Kelly

From: "ara.t.howard said:
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. :)

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
 
B

Bryan Richardson

Hi Bill,

Thanks for the reply. I hate Windows. :)

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! :(
 
A

ara.t.howard

Hi Bill,

Thanks for the reply. I hate Windows. :)

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! :(

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/
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,078
Latest member
MakersCBDBlood

Latest Threads

Top