Skip to content

Commit

Permalink
Calling exit inside a at_exit handler should not unwind or return
Browse files Browse the repository at this point in the history
  • Loading branch information
bew committed Dec 19, 2017
1 parent 1714f66 commit c616a95
Showing 1 changed file with 6 additions and 14 deletions.
20 changes: 6 additions & 14 deletions src/kernel.cr
Original file line number Diff line number Diff line change
Expand Up @@ -124,15 +124,18 @@ module AtExitHandlers
handlers << handler
end

@@handler_iterator : Iterator(Int32 ->)?

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

@@handlers.try &.reverse_each do |handler|
handler_iterator = @@handler_iterator ||= handlers.reverse_each

handler_iterator.each do |handler|
begin
handler.call status
rescue nested_exit : NestedExitError
status = nested_exit.status_code
rescue handler_ex
STDERR.puts "Error running at_exit handler: #{handler_ex}"
status = 1 if status.zero?
Expand Down Expand Up @@ -165,22 +168,11 @@ def at_exit(&handler : Int32 ->) : Nil
AtExitHandlers.add(handler)
end

class NestedExitError < Exception
getter status_code : Int32

def initialize(@status_code)
end
end

# Terminates execution immediately, returning the given status code
# to the invoking environment.
#
# Registered `at_exit` procs are executed.
def exit(status = 0) : NoReturn
if AtExitHandlers.running?
raise NestedExitError.new status
end

status = AtExitHandlers.run status
STDOUT.flush
STDERR.flush
Expand Down

0 comments on commit c616a95

Please sign in to comment.