11 responses to “Ruby exit, exit!, SystemExit and at_exit blunder”

  1. Avdi Grimm

    A good reminder; not enough people understand Ruby’s process termination system. Incidentally, I prefer `abort(“Some error message”)` to `exit(1)`. It sets the exit status to 1, and also sets the error message in the SystemExit exception.

    1. Deryl R. Doucette

      Yes, did not know about the abort() either! I’ve been hardcoding ‘exit 255′ in my scripts. Thanks!

  2. Jonathan Rochkind

    at_exit blocks are used with great caution and echo the original exit status when necessary.

    Any clue on how one would do this, is there any way an “at_exit” block can access the ‘original exit status’?

    Or wait, is the key thing just that you do not need to and should not call `exit` inside `at_exit` — at_exit shoudl do it’s thing without calling `exit`, and then when it’s done being executed the process will still exit on it’s own, with the original exit value. Is that right?

    1. Avdi Grimm

      You can always find out what the exit status is by looking at the SystemExit exception, which will be found in `$!` (aka `$ERROR_INFO` if you require ‘English’). If I may shamelessly self-promote for a moment, I go into this in depth in Exceptional Ruby.

  3. Rick Hull

    > Yes, I think putting a “exit” inside an “at_exit” block makes no sense

    Pardon the phrase, but this is the real WTF. Maybe at_exit good practices would be a good blog post. I’ve never had to use it so I’ve never looked into it myself. Also, I wholeheartedly recommend Avdi’s exceptional book.

  4. David Barri

    What a coincidence! I just blogged about something very similar!


  5. Jonathan Rochkind

    After running into my own weird at_exit related bug, I discovered this MRI bug report:


    I think a LOT of people’s at_exit related problems are actually due to this bug. Note that while the bug is marked fixed in the tracker, the reproduction still reproduces for me in 1.9.3p194, so I don’t think it’s made it into a release yet.

    And that bug report reproduction case also reveals something interesting — you ARE allowed to call `exit` in an `at_exit` block. It does not keep subsequent `at_exit` blocks from running. If everything is working properly, the exit code of the last `at_exit` block to call `exit` ‘wins’. But because of that bug, everything may not be working properly. There is a workaround with monkey-patch redefining `at_exit` in that bug report.

    That bug doesn’t actually account for YOUR problem as above. Your problem was a legitimate software error — don’t call ‘exit’ in an `at_exit` block unless you actually WANT to set the exit code in the `at_exit` block. If you don’t, and don’t need to call `exit` in it, you’re fine. If you DO need to call `exit’ in an at_exit block to set the exit code… then the MRI bug may interfere with your desires.