I'd like to be able to write a ruby program that can restart without dropping it's socket connections.
2 Answers
This program gets Google's homepage and then when you pass it SIG_INT via Ctrl-C it restarts the program and reads the output of the homepage from the open socket with Google.
#!/usr/bin/ruby
#simple_connector.rb
require 'socket'
puts "Started."
if ARGV[0] == "restart"
sock = IO.open(ARGV[1].to_i)
puts sock.read
exit
else
sock = TCPSocket.new('google.com', 80)
sock.write("GET /\n")
end
Signal.trap("INT") do
puts "Restarting..."
exec("ruby simple_connector.rb restart #{sock.fileno}")
end
while true
sleep 1
end
4 Comments
Paul
When restarting: simple_connector.rb:8:in
initialize': Bad file descriptor (Errno::EBADF) from simple_connector.rb:8:in open' from simple_connector.rb:8:in `<main>'ryantm
From ruby-doc.org/core-2.1.2/IO.html#method-i-close_on_exec-3D Ruby sets close-on-exec flags of all file descriptors by default since Ruby 2.0.0. So you don’t need to set by yourself. Also, unsetting a close-on-exec flag can cause file descriptor leak if another thread use fork() and exec() (via system() method for example). If you really needs file descriptor inheritance to child process, use spawn()‘s argument such as fd=>fd.
Paul
What I've done - have taken your example without any changes. Could you provide an example how to deal with close-on-exec flag the right way? Should I simply set it to true before exec?
ryantm
I messed around with it some but I didn't come up with a fully functioning example. Instead of
exec do spawn("ruby simple_connector.rb restart #{sock.fileno}", sock=>sock). Unfortunately, I think spawn differs from exec in other ways too.