From 27b081b61984c19d2c75dbbf911c2d128a08f690 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= Date: Tue, 17 Dec 2024 12:00:25 +0100 Subject: [PATCH 1/2] Add `Process::Status#exit_signal?` --- spec/std/process/status_spec.cr | 17 +++++++++++++++++ src/process/status.cr | 14 ++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/spec/std/process/status_spec.cr b/spec/std/process/status_spec.cr index 63136a2ddac7..aa170d73dbd6 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/process/status.cr b/src/process/status.cr index 28e6049238dc..ca3ae7dc627b 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. From ec05412090782bc475cdb44fd607ebf2a1af6380 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= Date: Tue, 17 Dec 2024 14:05:43 +0100 Subject: [PATCH 2/2] Use `#exit_signal?` in stdlib --- src/compiler/crystal/command.cr | 3 +-- src/process/status.cr | 20 +++++++++----------- 2 files changed, 10 insertions(+), 13 deletions(-) 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 ca3ae7dc627b..3698d8877314 100644 --- a/src/process/status.cr +++ b/src/process/status.cr @@ -292,10 +292,10 @@ class Process::Status {% if flag?(:win32) %} @exit_status.to_s(io) {% 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 << "]" @@ -309,15 +309,14 @@ class Process::Status {% if flag?(:win32) %} @exit_status.to_s(io) {% 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 @@ -330,11 +329,10 @@ class Process::Status {% if flag?(:win32) %} @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