Skip to content

Commit

Permalink
Pass an unhandled exception to at_exit block as second argument (#5906)
Browse files Browse the repository at this point in the history
* Pass an unhandled exception to at_exit block as second argument

Follow up #1921

It is better in some ways:

  - it does not need a new exception like `SystemExit`.
  - it does not break compatibility in most cases because block fill up lacking arguments.

* Add documentation for at_exit block arguments

* Update `at_exit` block arguments description

#5906 (comment)
Thank you @jhass.
  • Loading branch information
makenowjust authored and RX14 committed Apr 3, 2018
1 parent 82caaf0 commit 5056859
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 3 deletions.
16 changes: 16 additions & 0 deletions spec/std/kernel_spec.cr
Expand Up @@ -225,4 +225,20 @@ describe "at_exit" do
Unhandled exception: Kaboom!
OUTPUT
end

it "can get unhandled exception in at_exit handler" do
status, _, error = build_and_run <<-CODE
at_exit do |_, ex|
STDERR.puts ex.try &.message
end
raise "Kaboom!"
CODE

status.success?.should be_false
error.should contain <<-OUTPUT
Kaboom!
Unhandled exception: Kaboom!
OUTPUT
end
end
12 changes: 9 additions & 3 deletions src/kernel.cr
Expand Up @@ -127,7 +127,7 @@ module AtExitHandlers

class_property exception : Exception?

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

def self.add(handler)
raise "Cannot use at_exit from an at_exit handler" if @@running
Expand All @@ -142,7 +142,7 @@ module AtExitHandlers
# Run the registered handlers in reverse order
while handler = handlers.pop?
begin
handler.call status
handler.call status, exception
rescue handler_ex
STDERR.puts "Error running at_exit handler: #{handler_ex}"
status = 1 if status.zero?
Expand Down Expand Up @@ -180,7 +180,13 @@ end
# ```text
# goodbye cruel world
# ```
def at_exit(&handler : Int32 ->) : Nil
#
# The exit status code that will be returned by this program is passed to
# the block as its first argument. In case of any unhandled exception, it is
# passed as the second argument to the block, if the program terminates
# normally or `exit(status)` is called explicitly, then the second argument
# will be nil.
def at_exit(&handler : Int32, Exception? ->) : Nil
AtExitHandlers.add(handler)
end

Expand Down

0 comments on commit 5056859

Please sign in to comment.