Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWinnie Hellmann <winnie@gitlab.com>2017-10-18 21:52:53 +0300
committerWinnie Hellmann <winnie@gitlab.com>2017-10-18 21:52:53 +0300
commit7e72a6751fc954756f514396453042927766a785 (patch)
treeb0bf571e885791fb3bbd85bca8f06593a2e56b2b /lib/gitlab/git/popen.rb
parent03106288f92ac5ec9c4867cc1be9b070f157ccac (diff)
parent83b59da6549d3137f1424ee9bf16b95e4f72173e (diff)
Merge branch '10-1-stable-prepare-rc3' into '10-1-stable'
Prepare 10.1 RC3 release See merge request gitlab-org/gitlab-ce!14921
Diffstat (limited to 'lib/gitlab/git/popen.rb')
-rw-r--r--lib/gitlab/git/popen.rb63
1 files changed, 63 insertions, 0 deletions
diff --git a/lib/gitlab/git/popen.rb b/lib/gitlab/git/popen.rb
index 3d2fc471d28..b45da6020ee 100644
--- a/lib/gitlab/git/popen.rb
+++ b/lib/gitlab/git/popen.rb
@@ -5,6 +5,8 @@ require 'open3'
module Gitlab
module Git
module Popen
+ FAST_GIT_PROCESS_TIMEOUT = 15.seconds
+
def popen(cmd, path, vars = {})
unless cmd.is_a?(Array)
raise "System commands must be given as an array of strings"
@@ -27,6 +29,67 @@ module Gitlab
[@cmd_output, @cmd_status]
end
+
+ def popen_with_timeout(cmd, timeout, path, vars = {})
+ unless cmd.is_a?(Array)
+ raise "System commands must be given as an array of strings"
+ end
+
+ path ||= Dir.pwd
+ vars['PWD'] = path
+
+ unless File.directory?(path)
+ FileUtils.mkdir_p(path)
+ end
+
+ rout, wout = IO.pipe
+ rerr, werr = IO.pipe
+
+ pid = Process.spawn(vars, *cmd, out: wout, err: werr, chdir: path, pgroup: true)
+
+ begin
+ status = process_wait_with_timeout(pid, timeout)
+
+ # close write ends so we could read them
+ wout.close
+ werr.close
+
+ cmd_output = rout.readlines.join
+ cmd_output << rerr.readlines.join # Copying the behaviour of `popen` which merges stderr into output
+
+ [cmd_output, status.exitstatus]
+ rescue Timeout::Error => e
+ kill_process_group_for_pid(pid)
+
+ raise e
+ ensure
+ wout.close unless wout.closed?
+ werr.close unless werr.closed?
+
+ rout.close
+ rerr.close
+ end
+ end
+
+ def process_wait_with_timeout(pid, timeout)
+ deadline = timeout.seconds.from_now
+ wait_time = 0.01
+
+ while deadline > Time.now
+ sleep(wait_time)
+ _, status = Process.wait2(pid, Process::WNOHANG)
+
+ return status unless status.nil?
+ end
+
+ raise Timeout::Error, "Timeout waiting for process ##{pid}"
+ end
+
+ def kill_process_group_for_pid(pid)
+ Process.kill("KILL", -pid)
+ Process.wait(pid)
+ rescue Errno::ESRCH
+ end
end
end
end