diff --git a/test/lib/envutil.rb b/test/lib/envutil.rb index 5d3bce99ec..f4d63d5a0a 100644 --- a/test/lib/envutil.rb +++ b/test/lib/envutil.rb @@ -65,6 +65,41 @@ module EnvUtil end module_function :apply_timeout_scale + def terminate(pid, signal = :TERM, pgroup = nil, reprieve = 1) + reprieve = apply_timeout_scale(reprieve) if reprieve + + signals = Array(signal).select do |sig| + DEFAULT_SIGNALS[sig.to_s] or + DEFAULT_SIGNALS[Signal.signame(sig)] rescue false + end + signals |= [:ABRT, :KILL] + case pgroup + when 0, true + pgroup = -pid + when nil, false + pgroup = pid + end + while signal = signals.shift + begin + Process.kill signal, pgroup + rescue Errno::EINVAL + next + rescue Errno::ESRCH + break + end + if signals.empty? or !reprieve + Process.wait(pid) + else + begin + Timeout.timeout(reprieve) {Process.wait(pid)} + rescue Timeout::Error + end + end + end + $? + end + module_function :terminate + def invoke_ruby(args, stdin_data = "", capture_stdout = false, capture_stderr = false, encoding: nil, timeout: 10, reprieve: 1, timeout_error: Timeout::Error, stdout_filter: nil, stderr_filter: nil, @@ -72,7 +107,6 @@ module EnvUtil rubybin: EnvUtil.rubybin, precommand: nil, **opt) timeout = apply_timeout_scale(timeout) - reprieve = apply_timeout_scale(reprieve) if reprieve in_c, in_p = IO.pipe out_p, out_c = IO.pipe if capture_stdout @@ -108,35 +142,7 @@ module EnvUtil if (!th_stdout || th_stdout.join(timeout)) && (!th_stderr || th_stderr.join(timeout)) timeout_error = nil else - signals = Array(signal).select do |sig| - DEFAULT_SIGNALS[sig.to_s] or - DEFAULT_SIGNALS[Signal.signame(sig)] rescue false - end - signals |= [:ABRT, :KILL] - case pgroup = opt[:pgroup] - when 0, true - pgroup = -pid - when nil, false - pgroup = pid - end - while signal = signals.shift - begin - Process.kill signal, pgroup - rescue Errno::EINVAL - next - rescue Errno::ESRCH - break - end - if signals.empty? or !reprieve - Process.wait(pid) - else - begin - Timeout.timeout(reprieve) {Process.wait(pid)} - rescue Timeout::Error - end - end - end - status = $? + status = terminate(pid, signal, opt[:pgroup], reprieve) end stdout = th_stdout.value if capture_stdout stderr = th_stderr.value if capture_stderr && capture_stderr != :merge_to_stdout diff --git a/test/ruby/test_thread.rb b/test/ruby/test_thread.rb index 51c0338595..f133126934 100644 --- a/test/ruby/test_thread.rb +++ b/test/ruby/test_thread.rb @@ -967,7 +967,12 @@ _eom pid = cpid t0 = Time.now.to_f Process.kill(:SIGINT, pid) - Timeout.timeout(10) { Process.wait(pid) } + begin + Timeout.timeout(10) { Process.wait(pid) } + rescue Timeout::Error + EnvUtil.terminate(pid) + raise + end t1 = Time.now.to_f [$?, t1 - t0, err_p.read] end