diff --git a/lib/bundler/cli/exec.rb b/lib/bundler/cli/exec.rb index 2fdc614fbba..d6ac4536763 100644 --- a/lib/bundler/cli/exec.rb +++ b/lib/bundler/cli/exec.rb @@ -6,7 +6,7 @@ module Bundler class CLI::Exec attr_reader :options, :args, :cmd - RESERVED_SIGNALS = %w[SEGV BUS ILL FPE VTALRM KILL STOP].freeze + TRAPPED_SIGNALS = %w[INT].freeze def initialize(options, args) @options = options @@ -70,8 +70,7 @@ def kernel_load(file, *args) ui = Bundler.ui Bundler.ui = nil require "bundler/setup" - signals = Signal.list.keys - RESERVED_SIGNALS - signals.each {|s| trap(s, "DEFAULT") } + TRAPPED_SIGNALS.each {|s| trap(s, "DEFAULT") } Kernel.load(file) rescue SystemExit, SignalException raise diff --git a/spec/commands/exec_spec.rb b/spec/commands/exec_spec.rb index af88f3f0431..d094c1d5788 100644 --- a/spec/commands/exec_spec.rb +++ b/spec/commands/exec_spec.rb @@ -700,30 +700,60 @@ def bin_path(a,b,c) end end - context "signals being trapped by bundler" do - let(:executable) { strip_whitespace <<-RUBY } - #{shebang} - begin - Thread.new do - puts 'Started' # For process sync - STDOUT.flush - sleep 1 # ignore quality_spec - raise "Didn't receive INT at all" - end.join - rescue Interrupt - puts "foo" - end - RUBY + context "signal handling" do + let(:test_signals) do + open3_reserved_signals = %w[CHLD CLD PIPE] + reserved_signals = %w[SEGV BUS ILL FPE VTALRM KILL STOP EXIT] + bundler_signals = %w[INT] + + Signal.list.keys - (bundler_signals + reserved_signals + open3_reserved_signals) + end + + context "signals being trapped by bundler" do + let(:executable) { strip_whitespace <<-RUBY } + #{shebang} + begin + Thread.new do + puts 'Started' # For process sync + STDOUT.flush + sleep 1 # ignore quality_spec + raise "Didn't receive INT at all" + end.join + rescue Interrupt + puts "foo" + end + RUBY - it "receives the signal" do - skip "popen3 doesn't provide a way to get pid " unless RUBY_VERSION >= "1.9.3" + it "receives the signal", :ruby => ">= 1.9.3" do + bundle!("exec #{path}") do |_, o, thr| + o.gets # Consumes 'Started' and ensures that thread has started + Process.kill("INT", thr.pid) + end - bundle("exec #{path}") do |_, o, thr| - o.gets # Consumes 'Started' and ensures that thread has started - Process.kill("INT", thr.pid) + expect(out).to eq("foo") end + end - expect(out).to eq("foo") + context "signals not being trapped by bunder" do + let(:executable) { strip_whitespace <<-RUBY } + #{shebang} + + signals = #{test_signals.inspect} + result = signals.map do |sig| + Signal.trap(sig, "IGNORE") + end + puts result.select { |ret| ret == "IGNORE" }.count + RUBY + + it "makes sure no unexpected signals are restored to DEFAULT" do + test_signals.each do |n| + Signal.trap(n, "IGNORE") + end + + bundle!("exec #{path}") + + expect(out).to eq(test_signals.count.to_s) + end end end end