Module: Pigeon::Support
Instance Method Summary collapse
-
#daemonize(logger = nil) ⇒ Object
Uses the double-fork method to create a fully detached background process.
-
#find_writable_directory(*list) ⇒ Object
Finds the first directory in the given list that exists and is writable.
- #nap(time) ⇒ Object
-
#unique_id ⇒ Object
Returns a unique 160-bit identifier for this engine expressed as a 40 character hexadecimal string.
Instance Method Details
#daemonize(logger = nil) ⇒ Object
Uses the double-fork method to create a fully detached background process. Returns the process ID of the created process. May throw an exception if these processes could not be created.
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
# File 'lib/pigeon/support.rb', line 7 def daemonize(logger = nil) delay = 10 rfd, wfd = IO.pipe forked_pid = fork do rfd.close supervisor_pid = fork do relaunch = true while (relaunch) daemon_pid = fork do begin yield rescue SystemExit # Forced exit from supervisor process rescue Object => e if (logger) logger.error("Terminated with Exception: [#{e.class}] #{e}") logger.error(e.backtrace.join("\n")) Thread.list.each do |thread| logger.error("Stack trace of current threads") logger.error(thread.inspect) if (thread.backtrace) logger.error("\t" + thread.backtrace.join("\n\t")) end end end exit(-1) end end begin interrupted = false Signal.trap('INT') do interrupted = true Process.kill('INT', daemon_pid) relaunch = false end _, status = Process.wait2(daemon_pid) if (interrupted) logger.info("Supervisor #{Process.pid} received termination signal, shut down child #{daemon_pid}.") end # A non-zero exit status indicates some sort of error, so the # process will be relaunched after a short delay. relaunch = (status != 0) ensure # Reset Signal handler before forking again Signal.trap('INT') do end end if (relaunch) begin logger.info("Supervisor #{Process.pid} will relaunch in %d seconds" % delay) sleep(delay) rescue Interrupt logger.info("Supervisor #{Process.pid} abandoing restart because of termination") relaunch = false end else logger.info("Terminated normally.") end end end wfd.puts(supervisor_pid) wfd.flush wfd.close end Process.wait2(forked_pid) daemon_pid = rfd.readline rfd.close daemon_pid.to_i end |
#find_writable_directory(*list) ⇒ Object
Finds the first directory in the given list that exists and is writable. Returns nil if none match.
103 104 105 106 107 |
# File 'lib/pigeon/support.rb', line 103 def find_writable_directory(*list) list.flatten.compact.find do |dir| File.exist?(dir) and File.writable?(dir) end end |
#nap(time) ⇒ Object
97 98 99 |
# File 'lib/pigeon/support.rb', line 97 def nap(time) select(nil, nil, nil, time.to_f) end |
#unique_id ⇒ Object
Returns a unique 160-bit identifier for this engine expressed as a 40 character hexadecimal string. The first 32-bit sequence is a timestamp so these numbers increase over time and can be used to identify when a particular instance was launched. For informational purposes, the name of the host is appended to help identify the origin of the ident.
114 115 116 117 118 119 120 121 122 |
# File 'lib/pigeon/support.rb', line 114 def unique_id '%8x%s@%s' % [ Time.now.to_i, Digest::SHA1.hexdigest( '%.8f%8x' % [ Time.now.to_f, rand(1 << 32) ] )[0, 32], Socket.gethostname ] end |