Class: Mediakit::Process::Runner
- Inherits:
-
Object
- Object
- Mediakit::Process::Runner
show all
- Defined in:
- lib/mediakit/process/runner.rb
Defined Under Namespace
Classes: CommandNotFoundError, IOWatcher, TimeoutError, TimeoutTimer
Constant Summary
collapse
- DEFAULT_READ_TIMEOUT_INTERVAL =
30
Instance Attribute Summary collapse
Instance Method Summary
collapse
Constructor Details
#initialize(timeout: nil, nice: 0, logger: Logger.new(STDOUT)) ⇒ Runner
Returns a new instance of Runner.
20
21
22
23
24
|
# File 'lib/mediakit/process/runner.rb', line 20
def initialize(timeout: nil, nice: 0, logger: Logger.new(STDOUT))
@timeout = timeout
@nice = nice
@logger = logger || Mediakit::Utils::NullLogger.new
end
|
Instance Attribute Details
#logger ⇒ Object
Returns the value of attribute logger.
18
19
20
|
# File 'lib/mediakit/process/runner.rb', line 18
def logger
@logger
end
|
Instance Method Details
#build_command(bin, *args) ⇒ Object
66
67
68
69
70
71
72
73
|
# File 'lib/mediakit/process/runner.rb', line 66
def build_command(bin, *args)
command = build_command_without_options(bin, *args)
if @nice == 0
command
else
"nice -n #{ShellEscape.escape(@nice.to_s)} sh -c \"#{command}\""
end
end
|
#build_command_without_options(bin, *args) ⇒ Object
75
76
77
78
|
# File 'lib/mediakit/process/runner.rb', line 75
def build_command_without_options(bin, *args)
escaped_args = ShellEscape.escape(*args)
"#{bin} #{escaped_args}"
end
|
#force_kill_process(pid) ⇒ Object
106
107
108
109
110
|
# File 'lib/mediakit/process/runner.rb', line 106
def force_kill_process(pid)
::Process.kill('SIGKILL', pid)
rescue Errno::ESRCH => e
logger.warn("fail SIGKILL pid=#{pid} - #{e.message}, #{e.backtrace.join("\n")}")
end
|
#run(command, *args) ⇒ Object
#run(command, args) ⇒ Object
34
35
36
37
38
39
40
41
42
43
44
45
|
# File 'lib/mediakit/process/runner.rb', line 34
def run(bin, *args)
command = build_command(bin, *args)
begin
stdin, stdout, stderr, wait_thread = Open3.popen3(command)
stdin.close
exit_status, output, error_output = wait(stdout, stderr, wait_thread)
rescue Errno::ENOENT => e
raise(CommandNotFoundError, "Can't find command - #{command}, #{e.meessage}")
end
[exit_status, output, error_output]
end
|
#run_loop ⇒ Object
90
91
92
93
94
95
96
|
# File 'lib/mediakit/process/runner.rb', line 90
def run_loop
@loop.run
rescue => e
logger.warn(e.message)
logger.warn(e.backtrace.join("\n"))
end
|
#setup_watchers(stdout, stderr) ⇒ Object
80
81
82
83
84
85
86
87
88
|
# File 'lib/mediakit/process/runner.rb', line 80
def setup_watchers(stdout, stderr)
@timer = @timeout ? TimeoutTimer.new(@timeout, Thread.current) : nil
@out_watcher = IOWatcher.new(stdout) { |data| @timer.update if @timer; logger.info(data); }
@err_watcher = IOWatcher.new(stderr) { |data| @timer.update if @timer; logger.info(data); }
@loop = Coolio::Loop.new
@out_watcher.attach(@loop)
@err_watcher.attach(@loop)
@timer.attach(@loop) if @timer
end
|
#teardown_watchers ⇒ Object
98
99
100
101
102
103
104
|
# File 'lib/mediakit/process/runner.rb', line 98
def teardown_watchers
@loop.watchers.each { |w| w.detach if w.attached? }
@loop.stop if @loop.has_active_watchers?
rescue RuntimeError => e
logger.warn(e.message)
logger.warn(e.backtrace.join("\n"))
end
|
#wait(stdout, stderr, wait_thread) ⇒ Object
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
|
# File 'lib/mediakit/process/runner.rb', line 47
def wait(stdout, stderr, wait_thread)
begin
setup_watchers(stdout, stderr)
loop_thread = Thread.new { run_loop }
wait_thread.join
exit_status = (wait_thread.value.exitstatus == 0)
rescue Timeout::Error => error
force_kill_process(wait_thread.pid)
raise(error)
ensure
teardown_watchers
loop_thread.join if loop_thread
@out_watcher.read
@err_watcher.read
end
[exit_status, @out_watcher.data, @err_watcher.data]
end
|