Skip to content

Commit

Permalink
Use a separate list for exceptions registered to print after at_exit …
Browse files Browse the repository at this point in the history
…handlers
  • Loading branch information
bew committed Mar 11, 2018
1 parent 9206818 commit 17ed1c7
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 6 deletions.
27 changes: 24 additions & 3 deletions spec/std/kernel_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ describe "at_exit" do
OUTPUT
end

it "allow handlers to change the exit code with explicit `exit` call" do
it "allows handlers to change the exit code with explicit `exit` call" do
status, output = build_and_run <<-'CODE'
at_exit do |exit_code|
puts "first handler code, exit code: #{exit_code}"
Expand Down Expand Up @@ -135,7 +135,7 @@ describe "at_exit" do
OUTPUT
end

it "allow handlers to change the exit code with explicit `exit` call (2)" do
it "allows handlers to change the exit code with explicit `exit` call (2)" do
status, output = build_and_run <<-'CODE'
at_exit do |exit_code|
puts "first handler code, exit code: #{exit_code}"
Expand Down Expand Up @@ -165,7 +165,7 @@ describe "at_exit" do
OUTPUT
end

it "change final exit code when an handler raises an error" do
it "changes final exit code when an handler raises an error" do
status, output, error = build_and_run <<-'CODE'
at_exit do |exit_code|
puts "first handler code, exit code: #{exit_code}"
Expand Down Expand Up @@ -204,4 +204,25 @@ describe "at_exit" do
status.success?.should be_false
error.should eq "Error running at_exit handler: Cannot use at_exit from an at_exit handler\n"
end

it "shows unhandled exceptions after at_exit handlers" do
status, _, error = build_and_run <<-CODE
at_exit do
STDERR.puts "first handler code"
end
at_exit do
STDERR.puts "second handler code"
end
raise "Kaboom!"
CODE

status.success?.should be_false
error.should contain <<-OUTPUT
second handler code
first handler code
Unhandled exception: Kaboom!
OUTPUT
end
end
16 changes: 13 additions & 3 deletions src/kernel.cr
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ module AtExitHandlers
@@running = false

private class_getter(handlers) { [] of Int32 -> }
private class_getter(exceptions) { [] of Exception }

def self.add(handler)
raise "Cannot use at_exit from an at_exit handler" if @@running
Expand All @@ -134,15 +135,17 @@ module AtExitHandlers
end

def self.add_exception(ex : Exception)
# Prepend a handler for this exception. It will run after all at_exit
# handlers, to make sure the user sees the exception.
handlers.unshift ->(status : Int32) { ex.inspect_with_backtrace(STDERR) }
# at_exit handlers can't be cleared now, but might in the future.
# The exceptions are stored in a separate list to make sure it won't be cleared.

exceptions << ex
end

def self.run(status)
return status unless handlers = @@handlers
@@running = true

# Run the registered handlers in reverse order
while handler = handlers.pop?
begin
handler.call status
Expand All @@ -152,6 +155,13 @@ module AtExitHandlers
end
end

# Print the registered exception(s) after all at_exit handlers, to make sure
# the user sees them.
while ex = exceptions.pop?
STDERR.print "Unhandled exception: "
ex.inspect_with_backtrace(STDERR)
end

status
end
end
Expand Down

0 comments on commit 17ed1c7

Please sign in to comment.