Class: Slave::LifeLine

Inherits:
Object
  • Object
show all
Defined in:
lib/slave.rb,
lib/slave-1.2.1.rb

Overview

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.

Constant Summary collapse

FDS =

–{{{

ThreadSafeHash.new
DELEGATED =
%w( puts gets read write close flush each )

Instance Method Summary collapse

Constructor Details

#initializeLifeLine

Returns a new instance of LifeLine.



175
176
177
178
179
180
181
182
183
184
185
186
# File 'lib/slave.rb', line 175

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

Instance Method Details

#catch(*ignored) ⇒ Object



201
202
203
204
205
206
207
208
209
# File 'lib/slave.rb', line 201

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) ⇒ Object



268
269
270
# File 'lib/slave.rb', line 268

def cling &b
  on_cut{ begin; b.call if b; ensure; Kernel.exit; end }.join
end

#close_unused_sockets_after_forkingObject



211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
# File 'lib/slave.rb', line 211

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

#cutObject Also known as: release



234
235
236
237
238
239
# File 'lib/slave.rb', line 234

def cut
  raise unless owner?
  raise unless @socket
  @socket.close rescue nil
  FDS.delete object_id
end

#on_cut(&b) ⇒ Object



253
254
255
256
257
258
259
260
261
262
263
264
265
266
# File 'lib/slave.rb', line 253

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?Boolean

Returns:

  • (Boolean)


188
189
190
# File 'lib/slave.rb', line 188

def owner?
  Process.pid == @owner
end

#throw(*ignored) ⇒ Object



192
193
194
195
196
197
198
199
# File 'lib/slave.rb', line 192

def throw(*ignored)
  raise unless owner?
  @pair[-1].close
  @pair[-1] = nil
  @pid = Process.pid
  @socket = @pair[0]
  @socket.sync = true
end