summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorBob Van Landuyt <bob@vanlanduyt.co>2017-08-03 16:22:52 +0200
committerBob Van Landuyt <bob@vanlanduyt.co>2017-08-04 15:38:50 +0200
commit4b34720c0ca8b5459cc56a4e52e11e213ab6ae9a (patch)
treee1933965092a34fa266458d03b76a74c3c998f1d /lib
parent3a2aaed881f8925b08acd4204f3e130939c73946 (diff)
downloadgitlab-ce-4b34720c0ca8b5459cc56a4e52e11e213ab6ae9a.tar.gz
Use ruby's `File.stat` to check storage availability
Diffstat (limited to 'lib')
-rw-r--r--lib/gitlab/git/storage/forked_storage_check.rb34
1 files changed, 15 insertions, 19 deletions
diff --git a/lib/gitlab/git/storage/forked_storage_check.rb b/lib/gitlab/git/storage/forked_storage_check.rb
index 0e9e7ba596b..91d8241f17b 100644
--- a/lib/gitlab/git/storage/forked_storage_check.rb
+++ b/lib/gitlab/git/storage/forked_storage_check.rb
@@ -11,7 +11,7 @@ module Gitlab
end
def timeout_check(path, timeout_seconds)
- filesystem_check_pid = check_filesystem_in_fork(path)
+ filesystem_check_pid = check_filesystem_in_process(path)
deadline = timeout_seconds.seconds.from_now.utc
wait_time = 0.01
@@ -31,27 +31,23 @@ module Gitlab
status
end
- # This call forks out into a process, that process will then be replaced
- # With an `exec` call, since we fork out into a shell, we can create a
- # child process without needing an ActiveRecord-connection.
+ # This will spawn a new 2 processes to do the check:
+ # The outer child (waiter) will spawn another child process (stater).
#
- # Inside the shell, we use `& wait` to fork another child. We do this
- # to prevent leaving a zombie process when the parent gets killed by the
- # timeout.
- #
- # https://stackoverflow.com/questions/27892975/what-causes-activerecord-breaking-postgres-connection-after-forking
- # https://stackoverflow.com/questions/22012943/activerecordstatementinvalid-runtimeerror-the-connection-cannot-be-reused-in
- def check_filesystem_in_fork(path)
- fork do
- STDOUT.reopen('/dev/null')
- STDERR.reopen('/dev/null')
-
- exec("(#{test_script(path)}) & wait %1")
- end
+ # The stater is the process is performing the actual filesystem check
+ # the check might hang if the filesystem is acting up.
+ # In this case we will send a `KILL` to the waiter, which will still
+ # be responsive while the stater is hanging.
+ def check_filesystem_in_process(path)
+ spawn('ruby', '-e', ruby_check, path, [:out, :err] => '/dev/null')
end
- def test_script(path)
- "testpath=$(realpath #{Shellwords.escape(path)}) && stat \"$testpath\""
+ def ruby_check
+ <<~RUBY_FILESYSTEM_CHECK
+ inner_pid = fork { File.stat(ARGV.first) }
+ Process.waitpid(inner_pid)
+ exit $?.exitstatus
+ RUBY_FILESYSTEM_CHECK
end
end
end