Merge pull request #17722 from reitermarkus/ignore-interrupts
Make `ignore_interrupts` thread-safe.
This commit is contained in:
commit
988c44ce20
@ -433,13 +433,11 @@ class CurlDownloadStrategy < AbstractFileDownloadStrategy
|
||||
rescue ErrorDuringExecution
|
||||
raise CurlDownloadStrategyError, url
|
||||
end
|
||||
ignore_interrupts do
|
||||
cached_location.dirname.mkpath
|
||||
temporary_path.rename(cached_location)
|
||||
symlink_location.dirname.mkpath
|
||||
end
|
||||
cached_location.dirname.mkpath
|
||||
temporary_path.rename(cached_location)
|
||||
end
|
||||
|
||||
symlink_location.dirname.mkpath
|
||||
FileUtils.ln_s cached_location.relative_path_from(symlink_location.dirname), symlink_location, force: true
|
||||
rescue CurlDownloadStrategyError
|
||||
raise if urls.empty?
|
||||
|
||||
@ -349,30 +349,26 @@ module Kernel
|
||||
end
|
||||
end
|
||||
|
||||
def ignore_interrupts(_opt = nil)
|
||||
# rubocop:disable Style/GlobalVars
|
||||
$ignore_interrupts_nesting_level = 0 unless defined?($ignore_interrupts_nesting_level)
|
||||
$ignore_interrupts_nesting_level += 1
|
||||
IGNORE_INTERRUPTS_MUTEX = Thread::Mutex.new.freeze
|
||||
|
||||
$ignore_interrupts_interrupted = false unless defined?($ignore_interrupts_interrupted)
|
||||
old_sigint_handler = trap(:INT) do
|
||||
$ignore_interrupts_interrupted = true
|
||||
$stderr.print "\n"
|
||||
$stderr.puts "One sec, cleaning up..."
|
||||
end
|
||||
def ignore_interrupts
|
||||
IGNORE_INTERRUPTS_MUTEX.synchronize do
|
||||
interrupted = T.let(false, T::Boolean)
|
||||
old_sigint_handler = trap(:INT) do
|
||||
interrupted = true
|
||||
|
||||
begin
|
||||
yield
|
||||
ensure
|
||||
trap(:INT, old_sigint_handler)
|
||||
$stderr.print "\n"
|
||||
$stderr.puts "One sec, cleaning up..."
|
||||
end
|
||||
|
||||
$ignore_interrupts_nesting_level -= 1
|
||||
if $ignore_interrupts_nesting_level == 0 && $ignore_interrupts_interrupted
|
||||
$ignore_interrupts_interrupted = false
|
||||
raise Interrupt
|
||||
begin
|
||||
yield
|
||||
ensure
|
||||
trap(:INT, old_sigint_handler)
|
||||
|
||||
raise Interrupt if interrupted
|
||||
end
|
||||
end
|
||||
# rubocop:enable Style/GlobalVars
|
||||
end
|
||||
|
||||
def redirect_stdout(file)
|
||||
|
||||
@ -238,14 +238,12 @@ class SystemCommand
|
||||
}
|
||||
options[:chdir] = chdir if chdir
|
||||
|
||||
raw_stdin, raw_stdout, raw_stderr, raw_wait_thr = ignore_interrupts do
|
||||
Open3.popen3(
|
||||
env.merge({ "COLUMNS" => Tty.width.to_s }),
|
||||
[executable, executable],
|
||||
*args,
|
||||
**options,
|
||||
)
|
||||
end
|
||||
raw_stdin, raw_stdout, raw_stderr, raw_wait_thr = Open3.popen3(
|
||||
env.merge({ "COLUMNS" => Tty.width.to_s }),
|
||||
[executable, executable],
|
||||
*args,
|
||||
**options,
|
||||
)
|
||||
|
||||
write_input_to(raw_stdin)
|
||||
raw_stdin.close_write
|
||||
|
||||
@ -75,11 +75,13 @@ module Utils
|
||||
exit!(true)
|
||||
end
|
||||
|
||||
ignore_interrupts(:quietly) do # the child will receive the interrupt and marshal it back
|
||||
pid = T.must(pid)
|
||||
|
||||
begin
|
||||
begin
|
||||
socket = server.accept_nonblock
|
||||
rescue Errno::EAGAIN, Errno::EWOULDBLOCK, Errno::ECONNABORTED, Errno::EPROTO, Errno::EINTR
|
||||
retry unless Process.waitpid(T.must(pid), Process::WNOHANG)
|
||||
retry unless Process.waitpid(pid, Process::WNOHANG)
|
||||
else
|
||||
socket.send_io(write)
|
||||
socket.close
|
||||
@ -87,23 +89,24 @@ module Utils
|
||||
write.close
|
||||
data = read.read
|
||||
read.close
|
||||
Process.wait(T.must(pid)) unless socket.nil?
|
||||
|
||||
# 130 is the exit status for a process interrupted via Ctrl-C.
|
||||
# We handle it here because of the possibility of an interrupted process terminating
|
||||
# without writing its Interrupt exception to the error pipe.
|
||||
raise Interrupt if $CHILD_STATUS.exitstatus == 130
|
||||
|
||||
if data.present?
|
||||
error_hash = JSON.parse(T.must(data.lines.first))
|
||||
|
||||
e = ChildProcessError.new(error_hash)
|
||||
|
||||
raise rewrite_child_error(e)
|
||||
end
|
||||
|
||||
raise "Forked child process failed: #{$CHILD_STATUS}" unless $CHILD_STATUS.success?
|
||||
Process.waitpid(pid) unless socket.nil?
|
||||
rescue Interrupt
|
||||
Process.waitpid(pid)
|
||||
end
|
||||
|
||||
# 130 is the exit status for a process interrupted via Ctrl-C.
|
||||
raise Interrupt if $CHILD_STATUS.exitstatus == 130
|
||||
raise Interrupt if $CHILD_STATUS.termsig == Signal.list["INT"]
|
||||
|
||||
if data.present?
|
||||
error_hash = JSON.parse(T.must(data.lines.first))
|
||||
|
||||
e = ChildProcessError.new(error_hash)
|
||||
|
||||
raise rewrite_child_error(e)
|
||||
end
|
||||
|
||||
raise "Forked child process failed: #{$CHILD_STATUS}" unless $CHILD_STATUS.success?
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -43,12 +43,11 @@ class GitHubArtifactDownloadStrategy < AbstractFileDownloadStrategy
|
||||
rescue ErrorDuringExecution
|
||||
raise CurlDownloadStrategyError, url
|
||||
end
|
||||
ignore_interrupts do
|
||||
cached_location.dirname.mkpath
|
||||
temporary_path.rename(cached_location)
|
||||
symlink_location.dirname.mkpath
|
||||
end
|
||||
cached_location.dirname.mkpath
|
||||
temporary_path.rename(cached_location)
|
||||
end
|
||||
|
||||
symlink_location.dirname.mkpath
|
||||
FileUtils.ln_s cached_location.relative_path_from(symlink_location.dirname), symlink_location, force: true
|
||||
end
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user