Class: ZTK::Background
Overview
Background Processing Class
This class can be used to easily run a linear process in a background manner.
The before fork callback is called once in the parent process.
The after fork callback is called twice, once in the parent process and once in the child process.
Instance Attribute Summary (collapse)
-
- (Object) pid
Result Set.
-
- (Object) result
Result Set.
Instance Method Summary (collapse)
- - (Boolean) alive?
- - (Boolean) dead?
-
- (Background) initialize(configuration = {})
constructor
A new instance of Background.
-
- (Integer) process { ... }
Process in background.
-
- (Array<pid, status, data>) wait
Wait for the background process to finish.
Methods inherited from Base
build_config, #config, #direct_log, hash_config, log_and_raise, #log_and_raise
Constructor Details
- (Background) initialize(configuration = {})
Returns a new instance of Background
51 52 53 54 55 56 |
# File 'lib/ztk/background.rb', line 51 def initialize(configuration={}) super(configuration) @result = nil GC.respond_to?(:copy_on_write_friendly=) and GC.copy_on_write_friendly = true end |
Instance Attribute Details
- (Object) pid
Result Set
47 48 49 |
# File 'lib/ztk/background.rb', line 47 def pid @pid end |
- (Object) result
Result Set
47 48 49 |
# File 'lib/ztk/background.rb', line 47 def result @result end |
Instance Method Details
- (Boolean) alive?
128 129 130 |
# File 'lib/ztk/background.rb', line 128 def alive? (Process.getpgid(@pid).is_a?(Integer) rescue false) end |
- (Boolean) dead?
132 133 134 |
# File 'lib/ztk/background.rb', line 132 def dead? !alive? end |
- (Integer) process { ... }
Process in background.
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 96 97 |
# File 'lib/ztk/background.rb', line 65 def process(&block) !block_given? and log_and_raise(BackgroundError, "You must supply a block to the process method!") @child_reader, @parent_writer = IO.pipe @parent_reader, @child_writer = IO.pipe config.before_fork and config.before_fork.call(Process.pid) @pid = Process.fork do config.after_fork and config.after_fork.call(Process.pid) @parent_writer.close @parent_reader.close STDOUT.reopen("/dev/null", "a") STDERR.reopen("/dev/null", "a") STDIN.reopen("/dev/null") if !(data = block.call).nil? config.ui.logger.debug { "write(#{data.inspect})" } @child_writer.write(Base64.encode64(Marshal.dump(data))) end @child_reader.close @child_writer.close Process.exit!(0) end config.after_fork and config.after_fork.call(Process.pid) @child_reader.close @child_writer.close @pid end |
- (Array<pid, status, data>) wait
Wait for the background process to finish.
If a process successfully finished, it's return value from the process block is stored into the result set.
It's advisable to use something like the at_exit hook to ensure you don't leave orphaned processes. For example, in the at_exit hook you could call wait to block until the child process finishes up.
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 |
# File 'lib/ztk/background.rb', line 112 def wait config.ui.logger.debug { "wait" } pid, status = (Process.wait2(@pid) rescue nil) if !pid.nil? && !status.nil? data = (Marshal.load(Base64.decode64(@parent_reader.read.to_s)) rescue nil) config.ui.logger.debug { "read(#{data.inspect})" } !data.nil? and @result = data @parent_reader.close @parent_writer.close return [pid, status, data] end nil end |