Module: Workety
- Defined in:
- lib/workety/workety.rb
Overview
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
Defined Under Namespace
Classes: TestThread
Constant Summary collapse
- STOP_SELF_WATCHDOG_TIMEOUT =
65
Class Method Summary collapse
-
.abort ⇒ Object
Thread initialize/start occurs inside @mutex, so calling Workety.abort/stop/must_stop?/aborted? from within it will lead to “ThreadError: deadlock; recursive locking”.
- .aborted? ⇒ Boolean
- .join ⇒ Object
- .loop ⇒ Object
- .must_stop? ⇒ Boolean
- .rescue_abort ⇒ Object
- .start(class_name, user = nil, group = nil) ⇒ Object
- .stop ⇒ Object
- .stop_sequence(aborted) ⇒ Object
-
.stop_watchdog ⇒ Object
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.
Class Method Details
.abort ⇒ Object
Thread initialize/start occurs inside @mutex, so calling Workety.abort/stop/must_stop?/aborted? from within it will lead to “ThreadError: deadlock; recursive locking”
89 90 91 |
# File 'lib/workety/workety.rb', line 89 def abort stop_sequence(true) end |
.aborted? ⇒ Boolean
97 98 99 |
# File 'lib/workety/workety.rb', line 97 def aborted? @mutex.synchronize { @aborted } end |
.join ⇒ Object
67 68 69 |
# File 'lib/workety/workety.rb', line 67 def join rescue_exit { @thread.join } end |
.loop ⇒ Object
105 106 107 108 109 |
# File 'lib/workety/workety.rb', line 105 def loop until must_stop? yield end end |
.must_stop? ⇒ Boolean
101 102 103 |
# File 'lib/workety/workety.rb', line 101 def must_stop? @mutex.synchronize { @must_stop } end |
.rescue_abort ⇒ Object
112 113 114 115 116 117 118 119 120 |
# File 'lib/workety/workety.rb', line 112 def rescue_abort yield rescue ScriptError, StandardError => exception begin exception.report! ensure Workety.abort end end |
.start(class_name, user = nil, group = nil) ⇒ Object
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
# 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 |
.stop ⇒ Object
93 94 95 |
# File 'lib/workety/workety.rb', line 93 def stop stop_sequence(false) end |
.stop_sequence(aborted) ⇒ Object
71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
# 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 |
.stop_watchdog ⇒ Object
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
126 127 128 129 130 131 |
# 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 |