module Workety
Initialize, start, stop and join worker class Drop process privileges after initialize
initialize() then start() There is no strict order for stop and join - stop may be called before join
Use Workety.stop
to shutdown process from within worker Use Workety.abort
to shutdown and return exit code 1, thus leading to restart by watchdog
This is an implementation for threaded worker.
TODO: If worker does not have any threads then a different path should be given:
* no mutex/started/must_stop * no Signal.threaded_trap * no thread list on USR1 * Just instantiate the class and call .start on it, leaving signal handling to that class
Constants
- STOP_SELF_WATCHDOG_TIMEOUT
Public Class Methods
Thread
initialize/start occurs inside @mutex, so calling Workety.abort
/stop/must_stop?/aborted? from within it will lead to “ThreadError: deadlock; recursive locking”
# File lib/workety/workety.rb, line 89 def abort stop_sequence(true) end
# File lib/workety/workety.rb, line 97 def aborted? @mutex.synchronize { @aborted } end
# File lib/workety/workety.rb, line 67 def join rescue_exit { @thread.join } end
# File lib/workety/workety.rb, line 105 def loop until must_stop? yield end end
# File lib/workety/workety.rb, line 101 def must_stop? @mutex.synchronize { @must_stop } end
# File lib/workety/workety.rb, line 112 def rescue_abort yield rescue ScriptError, StandardError => exception begin exception.report! ensure Workety.abort end end
# File lib/workety/workety.rb, line 47 def start(class_name, user = nil, group = nil) rescue_exit do # Class initialize is the place to things you should do before dropping privilegies (like start listening at port 80). # @mutex.synchronize do Process.exit(!@aborted) if @must_stop @thread = class_name.constantize.new end Process.change_privilegies(user, group) if user || group @mutex.synchronize do Process.exit(!@aborted) if @must_stop @thread.start @started = true end end end
# File lib/workety/workety.rb, line 93 def stop stop_sequence(false) end
# File lib/workety/workety.rb, line 71 def stop_sequence(aborted) rescue_exit do @mutex.synchronize do @aborted = true if aborted unless @must_stop @must_stop = true Thread.rescue_exit { stop_watchdog } Thread.rescue_exit { @thread.stop } if @started end end end end
Timeout for stop() and join() When the process is stopped by a signal, watchdog or signal sender take care of timeout But when the process call Workety.stop
/abort by itself, this timeout function will ensure successful termination
# File lib/workety/workety.rb, line 126 def stop_watchdog sleep Workety::STOP_SELF_WATCHDOG_TIMEOUT Thread.log "Timeout stopping process" ensure Process.exit(false) end