17

Can i determine selves process exit status in at_exit block?

at_exit do
  if this_process_status.success?
    print 'Success'
  else
    print 'Failure'
  end
end
tig
  • 25,841
  • 10
  • 64
  • 96

2 Answers2

23

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
tig
  • 25,841
  • 10
  • 64
  • 96
  • 2
    just my opinion would be to give the "check" to tadman instead of yourself /shrug. – Reed Debaets Feb 15 '10 at 17:09
  • 1
    I think that the fullest answer should be checked. Check is most useful for other users looking for answer and I don't think that anything will change for me and tadman, whatever answer I will check. – tig Feb 16 '10 at 01:10
  • I think using `at_exit` for this is ok for small scripts. For larger apps, you should be using `exit` (or calling your own method to handle exits) at the intended exit points, and handling errors, exceptions, and signals explicitly. – Kelvin Oct 03 '12 at 18:30
  • What is the `($!.is_a?(SystemExit) && $!.success?)`? – Nakilon Jun 24 '22 at 15:23
  • 1
    @Nakilon Check if exit is happening due to explicit call to `exit` (or `raise SystemExit`) and exit code is successful (equal to `0`) – tig Jul 01 '22 at 16:49
  • @tig interesting. I wish the SystemExit had .to_i so you could do $!.to_i.zero? instead of it all. – Nakilon Jul 02 '22 at 09:05
  • @Nakilon It has also `status`, so you can `$!.status.zero?` (or even monkey-patch `to_i` alias), but you still need to check if it is a `SystemExit` first. – tig Jul 09 '22 at 11:20
20

Although the documentation on this is really thin, $! is set to be the last exception that occurs, and after an exit() call this is a SystemExit exception. Putting those two together you get this:

at_exit do
  if ($!.success?)
    print 'Success'
  else
    print 'Failure'
  end
end
tadman
  • 208,517
  • 23
  • 234
  • 262
  • That will be the case only if exit will be called. Surely I can be test if $! is nil or is SystemExit which answers true on success? But is it possible to get Process::Status object or it is not created for the top process? – tig Jul 18 '09 at 12:12
  • using your idea I got answer and posted but I don't know which answer is better to mark - yours or mine? – tig Jul 20 '09 at 16:52
  • Whatever works for you. Didn't know you could "answer" your own question, but okay. – tadman Jul 21 '09 at 18:54