Object
The signals that the engine cares about.
Create an Engine for running processes
@param [Hash] options
@option options [String] :formation (all=1) The process formation to use @option options [Fixnum] :port (5000) The base port to assign to processes @option options [String] :root (Dir.pwd) The root directory from which to run processes
# File lib/foreman/engine.rb, line 28 def initialize(options={}) @options = options.dup @options[:formation] ||= (options[:concurrency] || "all=1") @options[:timeout] ||= 5 @env = {} @mutex = Mutex.new @names = {} @processes = [] @running = {} @readers = {} # Self-pipe for deferred signal-handling (ala djb: http://cr.yp.to/docs/selfpipe.html) reader, writer = create_pipe reader.close_on_exec = true if reader.respond_to?(:close_on_exec) writer.close_on_exec = true if writer.respond_to?(:close_on_exec) @selfpipe = { :reader => reader, :writer => writer } # Set up a global signal queue # http://blog.rubybestpractices.com/posts/ewong/016-Implementing-Signal-Handlers.html Thread.main[:signal_queue] = [] end
Get the base port for this foreman instance
@returns [Fixnum] port The base port
# File lib/foreman/engine.rb, line 272 def base_port (options[:port] || env["PORT"] || ENV["PORT"] || 5000).to_i end
Clear the processes registered to this Engine
# File lib/foreman/engine.rb, line 150 def clear @names = {} @processes = [] end
Yield each Process in order
# File lib/foreman/engine.rb, line 239 def each_process process_names.each do |name| yield name, process(name) end end
deprecated
# File lib/foreman/engine.rb, line 277 def environment env end
Get the process formation
@returns [Fixnum] The formation count for the specified process
# File lib/foreman/engine.rb, line 215 def formation @formation ||= parse_formation(options[:formation]) end
Handle a HUP signal
# File lib/foreman/engine.rb, line 127 def handle_hangup puts "SIGHUP received" terminate_gracefully end
Handle an INT signal
# File lib/foreman/engine.rb, line 120 def handle_interrupt puts "SIGINT received" terminate_gracefully end
Invoke the real handler for signal sig. This shouldn’t be called directly by signal handlers, as it might invoke code which isn’t re-entrant.
@param [Symbol] sig the name of the signal to be handled
# File lib/foreman/engine.rb, line 98 def handle_signal(sig) case sig when :TERM handle_term_signal when :INT handle_interrupt when :HUP handle_hangup else system "unhandled signal #{sig}" end end
Handle a TERM signal
# File lib/foreman/engine.rb, line 113 def handle_term_signal puts "SIGTERM received" terminate_gracefully end
Send a signal to all processes started by this Engine
@param [String] signal The signal to send to each process
# File lib/foreman/engine.rb, line 179 def kill_children(signal="SIGTERM") if Foreman.windows? @running.each do |pid, (process, index)| system "sending #{signal} to #{name_for(pid)} at pid #{pid}" begin Process.kill(signal, pid) rescue Errno::ESRCH, Errno::EPERM end end else begin Process.kill signal, *@running.keys unless @running.empty? rescue Errno::ESRCH, Errno::EPERM end end end
Send a signal to the whole process group.
@param [String] signal The signal to send
# File lib/foreman/engine.rb, line 200 def killall(signal="SIGTERM") if Foreman.windows? kill_children(signal) else begin Process.kill "-#{signal}", Process.pid rescue Errno::ESRCH, Errno::EPERM end end end
Load a .env file into the env for this Engine
@param [String] filename A .env file to load into the environment
# File lib/foreman/engine.rb, line 171 def load_env(filename) @env.update Dotenv::Environment.new(filename) end
Register processes by reading a Procfile
@param [String] filename A Procfile from which to read processes to register
# File lib/foreman/engine.rb, line 159 def load_procfile(filename) options[:root] ||= File.dirname(filename) Foreman::Procfile.new(filename).entries do |name, command| register name, command, :cwd => options[:root] end self end
Wake the main thread up via the selfpipe when there’s a signal
# File lib/foreman/engine.rb, line 84 def notice_signal @selfpipe[:writer].write_nonblock( '.' ) rescue Errno::EAGAIN # Ignore writes that would block rescue Errno::EINT # Retry if another signal arrived while writing retry end
Get the port for a given process and offset
@param [Foreman::Process] process A Process associated with this engine @param [Fixnum] instance The instance of the process
@returns [Fixnum] port The port to use for this instance of this process
# File lib/foreman/engine.rb, line 260 def port_for(process, instance, base=nil) if base base + (@processes.index(process.process) * 100) + (instance - 1) else base_port + (@processes.index(process) * 100) + (instance - 1) end end
Get the Process for a specifid name
@param [String] name The process name
@returns [Foreman::Process] The Process for the specified name
# File lib/foreman/engine.rb, line 233 def process(name) @names.invert[name] end
List the available process names
@returns [Array] A list of process names
# File lib/foreman/engine.rb, line 223 def process_names @processes.map { |p| @names[p] } end
Register a process to be run by this Engine
@param [String] name A name for this process @param [String] command The command to run @param [Hash] options
@option options [Hash] :env A custom environment for this process
# File lib/foreman/engine.rb, line 140 def register(name, command, options={}) options[:env] ||= env options[:cwd] ||= File.dirname(command.split(" ").first) process = Foreman::Process.new(command, options) @names[process] = name @processes << process end
Set up deferred signal handlers
# File lib/foreman/engine.rb, line 66 def register_signal_handlers HANDLED_SIGNALS.each do |sig| if ::Signal.list.include? sig.to_s trap(sig) { Thread.main[:signal_queue] << sig ; notice_signal } end end end
Unregister deferred signal handlers
# File lib/foreman/engine.rb, line 76 def restore_default_signal_handlers HANDLED_SIGNALS.each do |sig| trap(sig, :DEFAULT) if ::Signal.list.include? sig.to_s end end
Generated with the Darkfish Rdoc Generator 2.