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

new() click to toggle source
# 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

catch(*ignored) click to toggle source
# 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
cling(&b) click to toggle source
# 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
close_unused_sockets_after_forking() click to toggle source
# 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
cut() click to toggle source
# 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
Also aliased as: release, release
on_cut(&b) click to toggle source
# 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
owner?() click to toggle source
# File lib/slave-1.2.1.rb, line 184
def owner?
  Process.pid == @owner
end
release()
Alias for: cut
throw(*ignored) click to toggle source
# 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