diff options
Diffstat (limited to 'spec')
-rw-r--r-- | spec/mixlib/shellout_spec.rb | 53 |
1 files changed, 52 insertions, 1 deletions
diff --git a/spec/mixlib/shellout_spec.rb b/spec/mixlib/shellout_spec.rb index 5e92a54..582aef4 100644 --- a/spec/mixlib/shellout_spec.rb +++ b/spec/mixlib/shellout_spec.rb @@ -825,7 +825,7 @@ describe Mixlib::ShellOut do end end - context 'with subprocess that takes longer than timeout', :focus do + context 'with subprocess that takes longer than timeout' do def ruby_wo_shell(code) parts = %w[ruby] parts << "--disable-gems" if ruby_19? @@ -889,6 +889,57 @@ describe Mixlib::ShellOut do end end + + context "and the child process forks grandchildren" do + let(:cmd) do + ruby_wo_shell(<<-CODE) + STDOUT.sync = true + trap(:TERM) { print "got term in child\n"; exit!(123) } + fork do + trap(:TERM) { print "got term in grandchild\n"; exit!(142) } + sleep 10 + end + sleep 10 + CODE + end + + it "should TERM the wayward child and grandchild" do + # note: let blocks don't correctly memoize if an exception is raised, + # so can't use executed_cmd + lambda { shell_cmd.run_command}.should raise_error(Mixlib::ShellOut::CommandTimeout) + shell_cmd.stdout.should include("got term in child") + shell_cmd.stdout.should include("got term in grandchild") + end + + end + context "and the child process forks grandchildren that don't respond to TERM" do + let(:cmd) do + ruby_wo_shell(<<-CODE) + STDOUT.sync = true + trap(:TERM) { print "got term in child\n" } + fork do + trap(:TERM) { print "got term in grandchild\n" } + sleep 10 + end + sleep 10 + CODE + end + + it "should TERM the wayward child and grandchild, then KILL whoever is left" do + # note: let blocks don't correctly memoize if an exception is raised, + # so can't use executed_cmd + lambda { shell_cmd.run_command}.should raise_error(Mixlib::ShellOut::CommandTimeout) + shell_cmd.stdout.should include("got term in child") + shell_cmd.stdout.should include("got term in grandchild") + + # A little janky. We get the process group id out of the command + # object, then try to kill a process in it to make sure none + # exists. Trusting the system under test like this isn't great but + # it's difficult to test otherwise. + lambda { Process.kill(:INT, shell_cmd.send(:child_pgid)) }.should raise_error(Errno::ESRCH) + end + + end end context 'with subprocess that exceeds buffersize' do |