Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions lib/parallel_tests.rb
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ def pid_file_path
ENV.fetch('PARALLEL_PID_FILE')
end

def stop_all_processes
pids.all.each { |pid| Process.kill(:INT, pid) }
def stop_all_processes(signal)
pids.all.each { |pid| Process.kill(signal, pid) }
rescue Errno::ESRCH, Errno::EPERM
# Process already terminated, do nothing
end
Expand Down
9 changes: 6 additions & 3 deletions lib/parallel_tests/cli.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@

module ParallelTests
class CLI
SIGNALS = %w[INT TERM]
def run(argv)
Signal.trap("INT") { handle_interrupt }
SIGNALS.each do |signal|
Signal.trap(signal) { handle_interrupt(signal) }
end

options = parse_options!(argv)

Expand All @@ -28,7 +31,7 @@ def run(argv)

private

def handle_interrupt
def handle_interrupt(signal)
@graceful_shutdown_attempted ||= false
Kernel.exit if @graceful_shutdown_attempted

Expand All @@ -46,7 +49,7 @@ def handle_interrupt
# using Thread workaround https://github.com/ddollar/foreman/issues/332
Thread.new do
if Gem.win_platform? || ((child_pid = ParallelTests.pids.all.first) && Process.getpgid(child_pid) != Process.pid)
ParallelTests.stop_all_processes
ParallelTests.stop_all_processes(signal)
end
end

Expand Down
15 changes: 15 additions & 0 deletions spec/integration_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -722,6 +722,21 @@ class A < Spinach::FeatureSteps
expect(result).to_not include("Should not get here either")
end

it "passes on term signal to child processes", unless: Gem.win_platform? do
timeout = 2
write(
"spec/test_spec.rb",
"sleep #{timeout}; describe { specify { p 'Should not get here' }; specify { p 'Should not get here either'} }"
)
pid = nil
Thread.new { sleep timeout - 1.0; Process.kill("TERM", pid) }
result = run_tests(["spec"], processes: 2, type: 'rspec', fail: true) { |io| pid = io.pid }

expect(result).to include("RSpec is shutting down")
expect(result).to_not include("Should not get here")
expect(result).to_not include("Should not get here either")
end

# Process.kill on Windows doesn't work as expected. It kills all process group instead of just one process.
it "exits immediately if another int signal is received", unless: Gem.win_platform? do
timeout = 2
Expand Down
Loading