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 49028a1
Showing 1 changed file with 6 additions and 18 deletions.
24 changes: 6 additions & 18 deletions src/kernel.cr
Original file line number Diff line number Diff line change
Expand Up @@ -117,22 +117,21 @@ end

# :nodoc:
module AtExitHandlers
class_getter? running = false

def self.add(handler)
handlers = @@handlers ||= [] of Int32 ->
handlers << handler
end

@@handler_iterator : Iterator(Int32 ->)?

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

handler_iterator = @@handler_iterator ||= handlers.reverse_each

@@handlers.try &.reverse_each do |handler|
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 +164,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 49028a1

Please sign in to comment.