Class: Slave::LifeLine
- Inherits:
-
Object
- Object
- Slave::LifeLine
- 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
- #catch(*ignored) ⇒ Object
- #cling(&b) ⇒ Object
- #close_unused_sockets_after_forking ⇒ Object
- #cut ⇒ Object (also: #release)
-
#initialize ⇒ LifeLine
constructor
A new instance of LifeLine.
- #on_cut(&b) ⇒ Object
- #owner? ⇒ Boolean
- #throw(*ignored) ⇒ Object
Constructor Details
#initialize ⇒ LifeLine
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_forking ⇒ Object
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. } (#{ 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 ⇒ Object 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
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 |