ruby at_exit exit status
using idea from tadman
at_exit do
if $!.nil? || ($!.is_a?(SystemExit) && $!.success?)
print 'success'
else
code = $!.is_a?(SystemExit) ? $!.status : 1
print "failure with code #{code}"
end
end
or without Perlisms:require 'English'
at_exit do
if $ERROR_INFO.nil? || ($ERROR_INFO.is_a?(SystemExit) && $ERROR_INFO.success?)
print 'success'
else
code = $ERROR_INFO.is_a?(SystemExit) ? $ERROR_INFO.status : 1
print "failure with code #{code}"
end
end
Ruby check whether program is currently being closed
See Below taken from my answer Here but seems more pertinent to your question than the one it is currently attached to:
Your best bet is probably a bit easier than signal trapping. The Kernel
Module
actually offers you an #at_exit
method that will be executed just prior to the program actually exiting.
Usage: (from Kernel#at_exit
Docs)
def do_at_exit(str1)
at_exit { print str1 }
end
at_exit { puts "cruel world" }
do_at_exit("goodbye ")
exit
"produces:"
goodbye cruel world
as you can see you can define multiple handlers which will be executed in reverse order when the program exits. Since Kernel
is included in Object
you can handle Object
specifics as well like
class People
at_exit {puts "The #{self.name} have left"}
end
exit
# The People have left
or even on instances p = People.new
p.send(:at_exit, &->{puts "We are leaving"})
# We are leaving
# The People have left
Additionally for more specific Object
based implementations you can take a look at ObjectSpace.define_finalizer
. example of usage:
class Person
def self.finalize(name)
proc {puts "Goodbye Cruel World -#{name}"}
end
def initialize(name)
@name = name
ObjectSpace.define_finalizer(self, self.class.finalize(@name))
end
end
Usage: p = Person.new("engineersmnky")
exit
# Goodbye Cruel World -engineersmnky
This may not be specifically what you want as this will fire when an Object
is garbage collected as well (not great for ephemeral objects) but if you have objects that should exist throughout the entire application this could still be used similar to an at_exit . Example# requiring WeakRef to allow garbage collection
# See: https://ruby-doc.org/stdlib-2.3.3/libdoc/weakref/rdoc/WeakRef.html
require 'weakref' #
p1 = Person.new("Engineer")
p2 = Person.new("Engineer's Monkey")
p2 = WeakRef.new(p2)
GC.start # just for this example
# Goodbye Cruel World -Engineer's Monkey
#=> nil
p2
#=> WeakRef::RefError: Invalid Reference - probably recycled
exit
# Goodbye Cruel World -Engineer
As you can see the defined finalizer for p2
fired because the Person
was gc'd but the program has not exited yet. p1
's finalizer waited until exit to fire because it retained its reference throughout the application. How can I ensure an operation runs before Rails exits, without using `at_exit`?
Ruby itself supports two hooks, BEGIN
and END
, which are run at the start of a script and as the interpreter stops running it.
See "What does Ruby's BEGIN do?" for more information.
The BEGIN
documentation says:
Designates, via code block, code to be executed unconditionally before sequential execution of the program begins. Sometimes used to simulate forward references to methods.
puts times_3(gets.to_i)
BEGIN {
def times_3(n)
n * 3
end
}
The END
documentations says:Designates, via code block, code to be executed just prior to program termination.
END { puts "Bye!" }
Access Ruby exit code in END {}
Kernel#exit
raises a SystemExit
exception and since the global variable $!
contains the current exception, you can get the exit status via $!.status
:
END {
puts "exit status: #{$!.status}"
}
exit 3
Output:exit status: 3
From the documentation:When an exception has been raised but not yet handled (in
rescue
,
ensure
,at_exit
andEND
blocks) the global variable$!
will contain
the current exception and$@
contains the current exception’s
backtrace.
ruby - how can i still do something when there's error (example: NameError)
Borrowing from an answer on a different thread, and definitely along the lines of what Marek commented, this is how you should handle errors in Ruby:
begin
# something which might raise an exception
rescue SomeExceptionClass => some_variable
# code that deals with some exception
rescue SomeOtherException => some_other_variable
# code that deals with some other exception
else
# code that runs only if *no* exception was raised
ensure
# ensure that this code always runs, no matter what
end
Original credit: Begin, Rescue and Ensure in Ruby? How do I find out which callbacks are registered with the at_exit method in Ruby?
You gotta love ruby :)
alias original_at_exit at_exit
def at_exit(*args, &block)
puts "registered at exit: #{caller * "\n"}"
original_at_exit *args, &block
end
ensure block of code runs when program exits
Signal 9 is non-catchable, non-ignorable kill, by design. Your at_exit
will not run because the operating system will simply terminate any process that receives this signal, not giving it any chance to do any extra work.
Related Topics
How to Send an Image on The Web in an Xmpp (Jabber) Message
Where to Reopen a Class in Ror
Is There a Command Line Framework for Ruby
Include Module in All Minitest Tests Like in Rspec
How to Handle 404 Not Found Errors in Nokogiri
How to Add a User Interrupt to an Infinite Loop
Converting Ruby Hashes to Arrays
Rails Gem Prawn, Image and Anchor
Ruby: Class C Includes Module M; Including Module N in M Does Not Affect C. What Gives
How to Mount a Sinatra Application Inside Another Sinatra App
How to Remove Backslashes from a JSON String
Error Installing Rdoc Documentation: Incompatible Encoding Regexp Match
Reading Files in a Zip Archive, Without Unzipping The Archive