class Slave::LifeLine
the LifeLine
class is used to communitacte between child and parent processes and to prevent child processes from ever becoming zombies or otherwise abandoned by their parents. the basic concept is that a socket pair is setup between child and parent. the child process, because it is a Slave
, sets up a handler such that, should it's socket ever grow stale, will exit the process. this class replaces the HeartBeat class from previous Slave
versions.
the LifeLine
class is used to communicate between child and parent processes and to prevent child processes from ever becoming zombies or otherwise abandoned by their parents. the basic concept is that a socket pair is setup between child and parent. the child process, because it is a Slave
, sets up a handler such that, should it's socket ever grow stale, will exit the process. this class replaces the HeartBeat class from previous Slave
versions.
Constants
- DELEGATED
- FDS
Public Class Methods
# File lib/slave-1.2.1.rb, line 171 def initialize @pair = Socket.pair Socket::AF_UNIX, Socket::SOCK_STREAM, 0 @owner = Process.pid @pid = nil @socket = nil @object_id = object_id @fds = @pair.map{|s| s.fileno} oid, fds = @object_id, @fds FDS[oid] = fds ObjectSpace.define_finalizer(self){ FDS.delete oid } end
Public Instance Methods
# File lib/slave-1.2.1.rb, line 197 def catch *ignored raise if owner? @pair[0].close @pair[0] = nil @pid = Process.pid @socket = @pair[-1] @socket.sync = true close_unused_sockets_after_forking end
# File lib/slave-1.2.1.rb, line 264 def cling &b on_cut{ begin; b.call if b; ensure; Kernel.exit; end }.join end
# File lib/slave-1.2.1.rb, line 207 def close_unused_sockets_after_forking begin to_delete = [] begin FDS.each do |oid, fds| next if oid == @object_id begin IO.for_fd(fds.first).close rescue Exception => e STDERR.puts "#{ e.message } (#{ e.class })\n#{ e.backtrace.join 10.chr }" ensure to_delete << oid end end ensure FDS.ex{ to_delete.each{|oid| FDS.delete oid rescue 42} } end GC.start rescue Exception => e 42 end end
# File lib/slave-1.2.1.rb, line 230 def cut raise unless owner? raise unless @socket @socket.close rescue nil FDS.delete object_id end
# File lib/slave-1.2.1.rb, line 249 def on_cut &b at_exit{ begin; b.call; ensure; b = nil; end if b} Thread.new(Thread.current){|current| Thread.current.abort_on_exception = true begin each{|*a|} rescue Exception current.raise $! 42 ensure begin; b.call; ensure; b = nil; end if b end } end
# File lib/slave-1.2.1.rb, line 184 def owner? Process.pid == @owner end
# File lib/slave-1.2.1.rb, line 188 def throw *ignored raise unless owner? @pair[-1].close @pair[-1] = nil @pid = Process.pid @socket = @pair[0] @socket.sync = true end