Saturday, June 23, 2007

Timing out Child Processes



I finally ran across a short Ruby powerpoint lecture by a CMU grad student to get me on the right track. Basically I wanted to spawn a process that me eventually killed (or disappears magically) after a certain amount of time. The answer is to use Timeout.

Here is my code. Notice I got rid of the fork.

#!/usr/bin/env ruby

require 'time'
require 'timeout'
require 'pp'


def time_cmd(command,timeout)
cmd_output = []
puts "Entering time_cmd at #{Time.now.tv_sec}"
begin
status = Timeout.timeout(timeout) do
p = IO.popen(command) do |f|
puts "pid: #{$$}"
f.each_line do |g|
cmd_output << g
system("ps aux | grep netstat")
end
system("ps aux | grep netstat")
end
end
pp status
rescue Timeout::Error
puts "\n#{command} completed at #{Time.now.tv_sec}"
return cmd_output
end
end

puts "pid: #{$$}"
puts time_cmd("netstat -dwh 1",3)
system("ps aux | grep netstat")


With the following output


franz-g4:~/dev/playin/ruby mdfranz$ ./angrytimeout.rb
pid: 3658
Entering time_cmd at 1182709241
pid: 3658
root 3659 2.2 0.0 27332 368 p2 S+ 1:20PM 0:00.01 netstat -d
root 3659 1.3 0.0 27332 368 p2 S+ 1:20PM 0:00.01 netstat -d
root 3659 0.1 0.0 27332 368 p2 S+ 1:20PM 0:00.01 netstat -d
root 3659 0.0 0.0 27332 368 p2 S+ 1:20PM 0:00.01 netstat -d

netstat -dwh 1 completed at 1182709244
input (Total) output
packets errs bytes packets errs bytes colls drops
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0


What I still haven't figured out how to do is get the process id of what is spawned by the popen so that I could Process.kill it if I needed to. I know I have been able to do this but it must have been with the Python subprocess module. which of course is more full featured.

Sunday, June 17, 2007

More Stupid Ruby Tricks: has_key("hell")

What is missing from the title. The bloody question mark! It serves me right for trying to code when fried from various domestic chores. The "undefined method" exception (like many cryptic Ruby error messages) wasn't terribly helpful either, or at least in my reduced state of competency, but maybe blogging on it will get it through my thick skull that method names that return booleans have a question mark suffix. I really don't see the point. How many (I'm sure some smartass will say TCL or some happy-ass functional language I could care less with that starts with an H or L) other languages have this idiom that confuses idiots. This seems seems unnecessary and certainly violates the "principle of least surprise" or perhaps I'm misapplying the term.
irb(main):003:0> d = {}
=> {}
irb(main):004:0> d[0] = 1
=> 1
irb(main):005:0> d[5] = 2
=> 2
irb(main):006:0> d
=> {5=>2, 0=>1}
irb(main):008:0> d.has_key(5)
NoMethodError: undefined method `has_key' for {5=>2, 0=>1}:Hash
from (irb):8
from :0
irb(main):009:0> d.has_key?(5)
=> true