lib/bluepill/process.rb in bluepill-0.0.51 vs lib/bluepill/process.rb in bluepill-0.0.52
- old
+ new
@@ -33,11 +33,15 @@
:monitor_children,
:child_process_factory,
:pid_command,
- :auto_start
+ :auto_start,
+
+ :supplementary_groups,
+
+ :stop_signals
]
attr_accessor :name, :watches, :triggers, :logger, :skip_ticks_until, :process_running
attr_accessor *CONFIGURABLE_ATTRIBUTES
attr_reader :children, :statistics
@@ -85,10 +89,11 @@
event :restart do
transition [:up, :down] => :restarting
end
before_transition any => any, :do => :notify_triggers
+ before_transition :stopping => any, :do => :clean_threads
after_transition any => :starting, :do => :start_process
after_transition any => :stopping, :do => :stop_process
after_transition any => :restarting, :do => :restart_process
@@ -99,10 +104,11 @@
@name = process_name
@event_mutex = Monitor.new
@watches = []
@triggers = []
@children = []
+ @threads = []
@statistics = ProcessStatistics.new
@actual_pid = options[:actual_pid]
self.logger = options[:logger]
checks.each do |name, opts|
@@ -132,10 +138,13 @@
self.skip_ticks_until = nil
# clear the memoization per tick
@process_running = nil
+ # Deal with thread cleanup here since the stopping state isn't used
+ clean_threads if self.unmonitored?
+
# run state machine transitions
super
if self.up?
self.run_watches
@@ -286,10 +295,34 @@
logger.warning "Stop command execution returned non-zero exit code:"
logger.warning result.inspect
end
end
+ elsif stop_signals
+ # issue stop signals with configurable delay between each
+ logger.warning "Sending stop signals to #{actual_pid}"
+ @threads << Thread.new(self, stop_signals.clone) do |process, stop_signals|
+ signal = stop_signals.shift
+ logger.info "Sending signal #{signal} to #{process.actual_pid}"
+ process.signal_process(signal.upcase) # send first signal
+
+ until stop_signals.empty?
+ # we already checked to make sure stop_signals had an odd number of items
+ delay = stop_signals.shift
+ signal = stop_signals.shift
+
+ logger.debug "Sleeping for #{delay} seconds"
+ sleep delay
+ #break unless signal_process(0) #break unless the process can be reached
+ unless process.signal_process(0)
+ logger.debug "Process has terminated."
+ break
+ end
+ logger.info "Sending signal #{signal} to #{process.actual_pid}"
+ process.signal_process(signal.upcase)
+ end
+ end
else
logger.warning "Executing default stop command. Sending TERM signal to #{actual_pid}"
signal_process("TERM")
end
self.unlink_pid # TODO: we only write the pid file if we daemonize, should we only unlink it if we daemonize?
@@ -318,10 +351,15 @@
self.stop_process
# the tick will bring it back.
end
end
+ def clean_threads
+ @threads.each { |t| t.kill }
+ @threads.clear
+ end
+
def daemonize?
!!self.daemonize
end
def monitor_children?
@@ -420,10 +458,11 @@
:environment => self.environment,
:pid_file => self.pid_file,
:logger => self.logger,
:stdin => self.stdin,
:stdout => self.stdout,
- :stderr => self.stderr
+ :stderr => self.stderr,
+ :supplementary_groups => self.supplementary_groups
}
end
def with_timeout(secs, &blk)
Timeout.timeout(secs.to_f, &blk)