shexecutor 0.0.7 → 0.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b7bd1eafe5b0bcf3c40dfb7abcb428642fd8f56a
4
- data.tar.gz: 5b24e222f42885b8e4e3e4f231d44eb623f60f09
3
+ metadata.gz: c90615e32be8148e01050f014d0bf7e107b403ad
4
+ data.tar.gz: 55607d1521893564995bea9da74153b084bd92ec
5
5
  SHA512:
6
- metadata.gz: 562083bd0cd5db122e2332955518bb19cc403940bb98fdadc8edcaacc26724269dec003a28bfdcbff5107f1d0376357fd4e5e038ff1d806582091531253f111f
7
- data.tar.gz: c46cd8e3d5f8835bf70bce083a02c692b75f35e87b818725e2dfee1e50104f0b66a48f7c99fdabb675f4dc54b7b43139abe55907f9293b108372b88f1dc61db2
6
+ metadata.gz: 54788b1980134c365b3b4c8cfb20c0d73ad74b3283e398f86e2b24662c57fcc382978dec80dfe10f463cf730ab7bab1244475dd1a32c609988a70ed888204b9d
7
+ data.tar.gz: becd1258cd4c5c1a526f180a419503430d5549c4064df9078300ba102d4100fb9229df812b6ca5b79787ec4d94894d00eea7ff993ed7bbd6073de8474f991af9
data/README.md CHANGED
@@ -20,6 +20,31 @@ For a full description of status, please see Process::Status
20
20
 
21
21
  This gem is sponsored by Hetzner (Pty) Ltd - http://hetzner.co.za
22
22
 
23
+ ## Initialization options:
24
+
25
+ Required / optional:
26
+
27
+ ```
28
+ {
29
+ :application_path # Path of the command to run
30
+ :params # Parameters to pass the command
31
+ }
32
+ ```
33
+
34
+ ```
35
+ @@default_options = {
36
+ :timeout => -1, # Seconds after which to raise Timeout::Error if not completed
37
+ :protect_against_injection => true, # look for spaces in and tainted application path
38
+ :stdout_path => nil, # file to append stdout to
39
+ :stderr_path => nil, # file to append stderr to
40
+ :append_stdout_path => true, # if true, will append, otherwise will overwrite
41
+ :append_stderr_path => true, # if true, will append, otherwise will overwrite
42
+ :replace => false, # replace the running process with the command
43
+ :wait_for_completion => false, # block until the command completes
44
+ :timeout_sig_kill_retry => 500 # if timeout occurs, send TERM, and send signal 9 if still present after X ms
45
+ }
46
+ ```
47
+
23
48
  ## Installation
24
49
 
25
50
  Add this line to your application's Gemfile:
@@ -1,3 +1,3 @@
1
1
  module SHExecutor
2
- VERSION = "0.0.7"
2
+ VERSION = "0.0.8"
3
3
  end
data/lib/shexecutor.rb CHANGED
@@ -3,14 +3,15 @@ require 'open3'
3
3
 
4
4
  module SHExecutor
5
5
  @@default_options = {
6
- :timeout => -1,
7
- :protect_against_injection => true,
8
- :stdout_path => nil,
9
- :stderr_path => nil,
10
- :append_stdout_path => true,
11
- :append_stderr_path => true,
12
- :replace => false,
13
- :wait_for_completion => false
6
+ :timeout => -1, # Seconds after which to raise Timeout::Error if not completed
7
+ :protect_against_injection => true, # look for spaces in and tainted application path
8
+ :stdout_path => nil, # file to append stdout to
9
+ :stderr_path => nil, # file to append stderr to
10
+ :append_stdout_path => true, # if true, will append, otherwise will overwrite
11
+ :append_stderr_path => true, # if true, will append, otherwise will overwrite
12
+ :replace => false, # replace the running process with the command
13
+ :wait_for_completion => false, # block until the command completes
14
+ :timeout_sig_kill_retry => 500 # if timeout occurs, send TERM, and send signal 9 if still present after X ms
14
15
  }
15
16
 
16
17
  def self.default_options
@@ -127,9 +128,9 @@ module SHExecutor
127
128
  def run_process(application_path, options = "")
128
129
  data_out = StringIO.new
129
130
  data_err = StringIO.new
130
- t0 = nil
131
+ @t0 = nil
131
132
  Open3::popen3(application_path, options) do |stdin, stdout, stderr, thr|
132
- t0 = thr
133
+ @t0 = thr
133
134
  # read srderr and stdout into buffers to prevent blocking
134
135
  t1 = Thread.new do
135
136
  IO.copy_stream(stdout, data_out)
@@ -151,7 +152,7 @@ module SHExecutor
151
152
  t1.join if not should_timeout?
152
153
  t2.join if not should_timeout?
153
154
  end
154
- return data_out, data_err, t0
155
+ return data_out, data_err, @t0
155
156
  end
156
157
 
157
158
  def block_process
@@ -170,17 +171,35 @@ module SHExecutor
170
171
  @result.join
171
172
  @result.value
172
173
  rescue Timeout::Error => ex
174
+ kill_process(@t0.pid)
173
175
  raise ex
174
176
  end
175
177
  end
176
178
 
179
+ def process?(pid)
180
+ begin
181
+ Process.getpgid(pid)
182
+ true
183
+ rescue Errno::ESRCH
184
+ false
185
+ end
186
+ end
187
+
188
+ def kill_process(pid)
189
+ return if pid.nil?
190
+ Process.kill("TERM", pid)
191
+ count = 0
192
+ while (count < (@options[:timeout_sig_kill_retry]/100) and process?(pid)) do
193
+ sleep 0.1
194
+ end
195
+ Process.kill(9, pid) if process?(pid)
196
+ end
197
+
177
198
  def fork_process
178
199
  validate
179
200
  @stdin_stream, @stdout_stream, @stderr_stream, @result = Open3::popen3(@options[:application_path], *@options[:params])
180
201
  end
181
202
 
182
- private
183
-
184
203
  def should_timeout?
185
204
  @options[:timeout] > 0
186
205
  end
@@ -27,7 +27,8 @@ describe 'Executor' do
27
27
  :append_stdout_path => false,
28
28
  :append_stderr_path => false,
29
29
  :replace => false,
30
- :wait_for_completion => true
30
+ :wait_for_completion => true,
31
+ :timeout_sig_kill_retry => 500
31
32
  }
32
33
  @iut = SHExecutor::Executor.new(iut_options)
33
34
  expect(@iut.options).to eq(iut_options)
@@ -207,7 +208,7 @@ describe 'Executor' do
207
208
  end
208
209
 
209
210
  context 'when asked to execute and block' do
210
- it 'should raise a TimeoutException if a timeout is specified and the process does not exit before' do
211
+ it 'should raise a Timeout::Error if a timeout is specified and the process does not exit before' do
211
212
  test_command = "/bin/sleep"
212
213
  test_params = ["5"]
213
214
  iut = SHExecutor::Executor.new({:timeout => 1, :wait_for_completion => true, :application_path => test_command, :params => test_params})
@@ -219,6 +220,16 @@ describe 'Executor' do
219
220
  expect(after - before).to be < 2.1
220
221
  end
221
222
 
223
+ it 'should kill the subprocess when a TimeoutError is raised' do
224
+ test_command = "/bin/sleep"
225
+ test_params = ["2"]
226
+ iut = SHExecutor::Executor.new({:timeout => 1, :wait_for_completion => true, :application_path => test_command, :params => test_params})
227
+ expect(Process).to receive(:kill)
228
+ expect {
229
+ iut.execute
230
+ }.to raise_error(Timeout::Error, "execution expired")
231
+ end
232
+
222
233
  it 'should call run_process with the command and parameters specified' do
223
234
  test_command = "/bin/ls"
224
235
  test_params = ["/tmp/"]
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shexecutor
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.7
4
+ version: 0.0.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ernst van Graan