Skip to content

Commit cd0890d

Browse files
committed
JT: Refactor raw_sh to start the process asynchronously
1 parent 9a02fb8 commit cd0890d

File tree

1 file changed

+50
-43
lines changed

1 file changed

+50
-43
lines changed

tool/jt.rb

Lines changed: 50 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
require 'json'
1818
require 'timeout'
1919
require 'yaml'
20-
require 'open3'
2120
require 'rbconfig'
2221
require 'pathname'
2322

@@ -288,22 +287,24 @@ def diff(expected, actual)
288287
`diff -u #{expected} #{actual}`
289288
end
290289

291-
def system_timeout(timeout, *args)
292-
begin
293-
pid = Process.spawn(*args)
294-
rescue SystemCallError
295-
return nil
296-
end
290+
def raw_sh_failed_status
291+
`false`
292+
$?
293+
end
297294

298-
begin
299-
Timeout.timeout timeout do
300-
Process.waitpid pid
301-
$?.success?
295+
def raw_sh_with_timeout(timeout, pid)
296+
if !timeout
297+
yield
298+
else
299+
begin
300+
Timeout.timeout(timeout) do
301+
yield
302+
end
303+
rescue Timeout::Error
304+
Process.kill('TERM', pid)
305+
yield # Wait and read the pipe if capture: true
306+
:timeout
302307
end
303-
rescue Timeout::Error
304-
Process.kill('TERM', pid)
305-
Process.waitpid pid
306-
nil
307308
end
308309
end
309310

@@ -318,43 +319,49 @@ def raw_sh(*args)
318319
STDERR.puts "$ #{printable_cmd(args)}"
319320
end
320321

321-
if use_exec
322-
result = exec(*args)
323-
elsif timeout
324-
result = system_timeout(timeout, *args)
325-
elsif capture
326-
if options.delete(:err) == :out
327-
out, status = Open3.capture2e(*args)
328-
else
329-
out = IO.popen(args) { |io| io.read }
330-
status = $?
331-
end
332-
result = status.success?
322+
exec(*args) if use_exec
323+
324+
if capture
325+
raise ":capture can only be combined with :err => :out" if options.include?(:out)
326+
pipe_r, pipe_w = IO.pipe
327+
options[:out] = pipe_w
328+
options[:err] = pipe_w if options[:err] == :out
329+
end
330+
331+
status = nil
332+
out = nil
333+
begin
334+
pid = Process.spawn(*args)
335+
rescue Errno::ENOENT # No such executable
336+
status = raw_sh_failed_status
333337
else
334-
result = system(*args)
338+
pipe_w.close if capture
339+
340+
result = raw_sh_with_timeout(timeout, pid) do
341+
out = pipe_r.read if capture
342+
_, status = Process.waitpid2(pid)
343+
end
344+
if result == :timeout
345+
status = raw_sh_failed_status
346+
end
347+
end
348+
349+
result = status.success?
350+
351+
if capture
352+
pipe_r.close
335353
end
336354

337-
if result
355+
if status.success? || continue_on_failure
338356
if capture
339357
out
340358
else
341-
true
359+
status.success?
342360
end
343-
elsif continue_on_failure
344-
false
345361
else
346-
status = $? unless capture
347362
$stderr.puts "FAILED (#{status}): #{printable_cmd(args)}"
348-
349-
if capture
350-
$stderr.puts out
351-
end
352-
353-
if status && status.exitstatus
354-
exit status.exitstatus
355-
else
356-
exit 1
357-
end
363+
$stderr.puts out if capture
364+
exit status.to_i
358365
end
359366
end
360367

0 commit comments

Comments
 (0)