Skip to content

Instantly share code, notes, and snippets.

@timuruski
Last active August 29, 2015 14:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save timuruski/361629b70327ebeef2f9 to your computer and use it in GitHub Desktop.
Save timuruski/361629b70327ebeef2f9 to your computer and use it in GitHub Desktop.
A mechanism for testing signals in Ruby processes.
class RubyProcess
WAIT_HELPER = <<-EOS
# Top-level method to signal the parent process
# and wait for an interrupt.
def wait_for(seconds)
# Signal parent we are ready.
Process.kill('USR1', Process.ppid)
# Wait for interrupt.
sleep(seconds)
end
EOS
def initialize(code, *args)
cmd = ['ruby'] + args
@io = IO.popen(cmd, 'w+', err: [:child, :out])
@io.write(WAIT_HELPER)
@io.write(code)
end
attr_reader :io, :status
def run_and_send(signal)
# Prefer to do this without trap, but $? does't get set when
# inside a rescue for some reason. Maybe use fork to avoid cleanup?
usr1_handler = trap('USR1') do
Process.kill(signal, io.pid)
end
io.close_write
@pid, @status = Process.waitpid2(io.pid)
ensure
trap('USR1', usr1_handler)
end
def output
io.readlines
end
end
if $0 == __FILE__
ruby = RubyProcess.new <<-EOS
trap('INT') { exit }
wait_for 1.0
# Fail if no interrupt is received.
raise 'No Interrupt received'
EOS
ruby.run_and_send('INT')
puts ruby.status
puts ruby.output
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment