43

The abort documentation says abort will

Terminate execution immediately, effectively by calling Kernel.exit(false).

What exactly does "immediately" mean? What is the difference between abort and exit with non-true status?

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
x-yuri
  • 16,722
  • 15
  • 114
  • 161
  • 1
    One useful post is - http://stackoverflow.com/questions/5295394/what-is-the-difference-between-exit-and-exit-in-ruby – Arup Rakshit Apr 28 '14 at 12:11

1 Answers1

66

"Exit, Exit! Abort, Raise…Get Me Outta Here!" describes everything you'd want to know I think.

In short:

  • Kernel.exit(code) "exits" the script immediately and returns the code to the OS, however, just before doing it, it calls any registered at_exit handler that your code could have registered.
  • Kernel.exit!(code) does the same, but exits immediatelly, no at_exit handlers called.
  • Kernel.abort(message) takes a message that will be printed to STDERR just before exiting with a failure code=1.

Different values of exit codes are barely suitable for detecting problems and debugging the code. However, they are very simple to use and making the parent process read them is almost trivial. Hence, exit and exit!.

If you can spend more time and make the error checking more robust, you'll need some serious error messages, not just codes. Traditionally, you can print them to STDERR if it exists. You can print manually to STDERR via normal puts, but exit-codes will still be used at the lowest level.

Printing to STDERR does not mark your job automatically as failed, so, abort was created to allow you to write and quit easily. A default exit code of 1 is enough to mark the FAIL condition, as it's assumed that all the real contextual information will be included in the error messages provided by you.

Also note that any unhanded exceptions, such as raise "wtf" with no rescue anywhere, actually behave as if calling Kernel.abort: they print to STDERR and use exitcode=1.

You said exit(false) but the exit! documentation says that the parameter is status code to be used.

I've just checked that on Windows and Ruby 1.9.3:

exit 0       # quits with code: 0
exit 1       # quits with code: 1
exit false   # quits with code: 1
exit true    # quits with code: 0

which really surprises me, as I'd assume that false would be coerced to 0 in the traditional C way. So, maybe you should rather be using integers like 0 or 1 to be perfectly clear about what code will be used.

Per Lundberg
  • 3,837
  • 1
  • 36
  • 46
quetzalcoatl
  • 32,194
  • 8
  • 68
  • 107
  • Can you provide sample examples... with each of your statement... ? Which would make this answer more helpful. – Arup Rakshit Apr 28 '14 at 12:08
  • @ArupRakshit: I actually was in the middle of edit'o'writing it :) – quetzalcoatl Apr 28 '14 at 12:09
  • Okay,,, Go ahead then! :-) – Arup Rakshit Apr 28 '14 at 12:09
  • So I figure, `exit` is a general way to terminate a program. `abort` is there if you're going to provide a message along with exit code, and you're fine with exit code `1`. `exit!` allows you to skip `at_exit` handlers. Can't see use case for that though. – x-yuri Apr 28 '14 at 13:23
  • 2
    `exit(false)` is a quote from [documentation](http://ruby-doc.org/core-2.1.1/Kernel.html#method-i-abort), you must be using a simplified version of it. Also, the [article](http://www.sitepoint.com/exit-exit-abort-raise-get-me-outta-here/) you linked says: "There’s a convention in the Unix world that an exit code equal to 0 means that the program was successful. Any other exit code denotes some kind of failure." The same goes for `windows`. – x-yuri Apr 28 '14 at 13:23
  • And it appears "immediately" doesn't mean much in description of `abort`. The one that exits immediately is `exit!`, I take it. – x-yuri Apr 28 '14 at 13:27
  • @x-yuri: (1) `exit/exit!/abort` - yes that's right. (2) `exit(false)` - I know that convention well. Note that `exit` comes from C. Also, `exit(0)` means success and non-zero means failure. In Ruby `exit(N)`, function accepts integers and passes them directly to OS. OK! But, in C,`exit(false)` would end up in exitcode of 0, and `exit(true)` in non-zero, while Ruby it's opposite. I think it's somewhat confusing, that's all. (3) I'm pretty sure that `abort` calls `exit` which raises an exception, a usually unhandled one. OTOH, I think that `exit!` terminates the process by some native func. – quetzalcoatl Apr 28 '14 at 15:17
  • (2) `in C,exit(false) would end up in exitcode of 0, and exit(true) in non-zero` I bet people don't usually pass boolean values to `exit` function, particularly considering there are [`EXIT_SUCCESS` and `EXIT_FAILURE` macroses](http://stackoverflow.com/a/2425227/52499). Also, passing them in `C` would be confusing, because `exit(false)` results in successful termination of the program. So, `ruby`'s behavior is fine by me. Although, I understand, that people coming from `C` might automatically translate `false` into `0` and get confused. But that's not to be expected of `ruby`. – x-yuri Apr 28 '14 at 17:30
  • (3) Still, with `abort` `at_exit` handlers are executed. So, I believe it's `exit!` that is "immediate", not the other two. – x-yuri Apr 28 '14 at 17:33
  • The reason exit(true) returns 0 is because the program exit status convention of Unix/Linux/Posix is the opposite of the C boolean value convention. "Success" exit status in Posix is 0. Anything non-zero is failure and the value can be optionally used to communicate/distinguish the type of failure. It would be strange if exit(true) meant that your program had failed and exit(false) meant that it had succeeded, even though that more closely follows the C boolean value convention. – BobDoolittle Nov 04 '15 at 21:33