I'm writing a script that might exit normally in many different points in the program. The script currently always outputs a message to STDOUT in an ensure block, sorta like this:
begin
exit
ensure
puts "my message"
end
The problem is that if the script crashes, the message is output anyway, followed by the error messages. What I want to do is only output the message on an exit 0, something like this:
begin
exit 1
ensure
if is_this_a_normal_exit?()
puts 'my messsage'
end
end
Is there a way to do that?
When calling exit
, this is generally Kernel#exit
. This method basically throws a SystemExit
exception which may eventually result in the program being exited.
You can either rescue this exception or check it in the ensure block:
begin
exit
rescue SystemExit => e
puts "my message" if e.success?
# re-raise the error to actually cause the program to exit
raise
ensure
# Here you can still add code which is executed after handling
# (or not handling) any exceptions. If there was an exception,
# you can access it here with the $! global variable.
end
Note that there are other possible causes of a program being exited, some of which you can't catch at all (e.g. when calling Kernel#exit!
or when you or some other process sends a signal like SIGKILL
to kill your program). Also, when using threads, the SystemExit
exception may not be propagated to the main thread.