From 5545bcae7cc966d849ff1423b2d1005c0d00dc8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= Date: Wed, 18 Dec 2024 17:46:06 +0100 Subject: [PATCH] Add `Process::Status#exit_signal?` (#15284) --- spec/std/process/status_spec.cr | 17 +++++++++++++++++ src/compiler/crystal/command.cr | 3 +-- src/process/status.cr | 34 ++++++++++++++++++++++----------- 3 files changed, 41 insertions(+), 13 deletions(-) diff --git a/spec/std/process/status_spec.cr b/spec/std/process/status_spec.cr index 31c86be4aae9..124a2b58add4 100644 --- a/spec/std/process/status_spec.cr +++ b/spec/std/process/status_spec.cr @@ -99,6 +99,13 @@ describe Process::Status do err1.hash.should eq(err2.hash) end + it "#exit_signal?" do + Process::Status.new(exit_status(0)).exit_signal?.should be_nil + Process::Status.new(exit_status(1)).exit_signal?.should be_nil + + status_for(:interrupted).exit_signal?.should eq({% if flag?(:unix) %}Signal::INT{% else %}nil{% end %}) + end + {% if flag?(:unix) && !flag?(:wasi) %} it "#exit_signal" do Process::Status.new(Signal::HUP.value).exit_signal.should eq Signal::HUP @@ -110,6 +117,16 @@ describe Process::Status do Process::Status.new(unknown_signal.value).exit_signal.should eq unknown_signal end + it "#exit_signal?" do + Process::Status.new(Signal::HUP.value).exit_signal?.should eq Signal::HUP + Process::Status.new(Signal::INT.value).exit_signal?.should eq Signal::INT + last_signal = Signal.values[-1] + Process::Status.new(last_signal.value).exit_signal?.should eq last_signal + + unknown_signal = Signal.new(126) + Process::Status.new(unknown_signal.value).exit_signal?.should eq unknown_signal + end + it "#normal_exit? with signal code" do Process::Status.new(0x00).normal_exit?.should be_true Process::Status.new(0x01).normal_exit?.should be_false diff --git a/src/compiler/crystal/command.cr b/src/compiler/crystal/command.cr index 3ce4fcd71550..cc6f39657f64 100644 --- a/src/compiler/crystal/command.cr +++ b/src/compiler/crystal/command.cr @@ -316,8 +316,7 @@ class Crystal::Command private def exit_message(status) case status.exit_reason when .aborted?, .session_ended?, .terminal_disconnected? - if status.signal_exit? - signal = status.exit_signal + if signal = status.exit_signal? if signal.kill? "Program was killed" else diff --git a/src/process/status.cr b/src/process/status.cr index 6598008b4e6f..0b7a3c827fb8 100644 --- a/src/process/status.cr +++ b/src/process/status.cr @@ -223,6 +223,20 @@ class Process::Status {% end %} end + # Returns the exit `Signal` or `nil` if there is none. + # + # On Windows returns always `nil`. + # + # * `#exit_reason` is a portable alternative. + def exit_signal? : Signal? + {% if flag?(:unix) && !flag?(:wasm32) %} + code = signal_code + unless code.zero? + Signal.new(code) + end + {% end %} + end + # Returns the exit code of the process if it exited normally (`#normal_exit?`). # # Raises `RuntimeError` if the status describes an abnormal exit. @@ -283,10 +297,10 @@ class Process::Status @exit_status.to_s(io) end {% else %} - if normal_exit? - exit_code.inspect(io) + if signal = exit_signal? + signal.inspect(io) else - exit_signal.inspect(io) + exit_code.inspect(io) end {% end %} io << "]" @@ -325,15 +339,14 @@ class Process::Status @exit_status.to_s(io) end {% else %} - if normal_exit? - io << exit_code - else - signal = exit_signal + if signal = exit_signal? if name = signal.member_name io << name else signal.inspect(io) end + else + io << exit_code end {% end %} end @@ -347,11 +360,10 @@ class Process::Status {% if flag?(:win32) %} name_for_win32_exit_status || @exit_status.to_s {% else %} - if normal_exit? - exit_code.to_s - else - signal = exit_signal + if signal = exit_signal? signal.member_name || signal.inspect + else + exit_code.to_s end {% end %} end