Skip to content

Commit

Permalink
Change Process::Status#to_s to hex format on Windows (#15285)
Browse files Browse the repository at this point in the history
Status numbers on Windows are usually represented in hexadecimal notation. This applies that for all large exit status values (above `UInt16::MAX`, inspired from https://cs.opensource.google/go/go/+/refs/tags/go1.23.4:src/os/exec_posix.go;l=117-121).

This again improves usability because it's easier to interpret unknown status values and compare them with listings sharing the typical number format.

In #15283 we already changed `Status#to_s` to print the name of known values. But not all status codes are named.
  • Loading branch information
straight-shoota authored Dec 20, 2024
1 parent 5545bca commit 22fb31b
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 3 deletions.
16 changes: 16 additions & 0 deletions spec/std/process/status_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,14 @@ describe Process::Status do
assert_prints Process::Status.new(Signal.new(126).value).to_s, "Signal[126]"
end
{% end %}

{% if flag?(:win32) %}
it "hex format" do
assert_prints Process::Status.new(UInt16::MAX).to_s, "0x0000FFFF"
assert_prints Process::Status.new(0x01234567).to_s, "0x01234567"
assert_prints Process::Status.new(UInt32::MAX).to_s, "0xFFFFFFFF"
end
{% end %}
end

describe "#inspect" do
Expand Down Expand Up @@ -302,5 +310,13 @@ describe Process::Status do
assert_prints Process::Status.new(unknown_signal.value).inspect, "Process::Status[Signal[126]]"
end
{% end %}

{% if flag?(:win32) %}
it "hex format" do
assert_prints Process::Status.new(UInt16::MAX).inspect, "Process::Status[0x0000FFFF]"
assert_prints Process::Status.new(0x01234567).inspect, "Process::Status[0x01234567]"
assert_prints Process::Status.new(UInt32::MAX).inspect, "Process::Status[0xFFFFFFFF]"
end
{% end %}
end
end
16 changes: 13 additions & 3 deletions src/process/status.cr
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ class Process::Status
if name = name_for_win32_exit_status
io << "LibC::" << name
else
@exit_status.to_s(io)
stringify_exit_status_windows(io)
end
{% else %}
if signal = exit_signal?
Expand Down Expand Up @@ -336,7 +336,7 @@ class Process::Status
if name = name_for_win32_exit_status
io << name
else
@exit_status.to_s(io)
stringify_exit_status_windows(io)
end
{% else %}
if signal = exit_signal?
Expand All @@ -358,7 +358,7 @@ class Process::Status
# A signal exit status prints the name of the `Signal` member (`HUP`, `INT`, etc.).
def to_s : String
{% if flag?(:win32) %}
name_for_win32_exit_status || @exit_status.to_s
name_for_win32_exit_status || String.build { |io| stringify_exit_status_windows(io) }
{% else %}
if signal = exit_signal?
signal.member_name || signal.inspect
Expand All @@ -367,4 +367,14 @@ class Process::Status
end
{% end %}
end

private def stringify_exit_status_windows(io)
# On Windows large status codes are typically expressed in hexadecimal
if @exit_status >= UInt16::MAX
io << "0x"
@exit_status.to_s(base: 16, upcase: true).rjust(io, 8, '0')
else
@exit_status.to_s(io)
end
end
end

0 comments on commit 22fb31b

Please sign in to comment.