27

I see in a lot of legacy software and bad tutorials on the Internet that recommend using exit(-1), return -1 or similar to represent "abnormal termination". The problem is, in POSIX at least, -1 has never been and is not a valid status code. man 3 exit illustrates that exit() returns the value of status & 0377 to the parent, meaning that -1 becomes 255. On non-POSIX systems, EXIT_FAILURE is recommended for portability. But I never see "-1 means abnormal termination" in conjunction with "EXIT_FAILURE may be something other than 1", indicating that they clearly believe "-1" is conventional even on non-POSIX systems.

Here's an example of a StackOverflow question that perpetuates this. The software "unrealircd" is also an example of a program that uses exit(-1) to terminate the program. In practice, this makes it difficult to interface with systemd.

Where did this anti-pattern come from? Is it valid in some context?

8
  • 1
    "Unix-like systems have a strong convention that an exit status of 0 denotes success, and any non-zero exit status denotes failure... This convention is pretty much hard wired into Unix shells..." (Non-zero exit status for clean exit)
    – gnat
    Commented Apr 2, 2016 at 19:31
  • @gnat According to the libc manual the exit status is explicitly 0 to 255 inclusive. If there's an answer somewhere that states that negative values were at one point valid, I would accept that, but I find that highly doubtful.
    – user222973
    Commented Apr 2, 2016 at 19:39
  • 1
    @gnat "255" easily fits into an unsigned char.
    – user222973
    Commented Apr 2, 2016 at 19:46
  • 1
  • 1
    @gnat A byte in "Java" is not an unsigned char, it is more equivalent to a char since its range of values is -128 to 127. Further, I already stated "-1" gets converted to "255" in my question body.
    – user222973
    Commented Apr 2, 2016 at 19:50

1 Answer 1

26

Almost all Unix computers use twos-complement for integers, and in twos-complement -1 is always "all bits 1" regardless of the word size. If you want the largest possible exit code regardless of the size of the program's exit status, using -1 and letting the library truncate it conveniently does the trick.

That's useful because when scripts or programs have more than one possible exit status (see grep for a simple example) the meaningful ones are usually assigned to the smallest numbers, making the largest possible exit code a good one to use for "unknown error" or "abort" since it's unlikely to ever conflict with a meaningful status value.

2
  • Take glibc as an example, which implements exit() as status &= 0xff. Is there a "word size" in which -1 & 0xff is not 255? Of course not, because the whole purpose is to make it fit in the range of 0-255. Regardless, your last sentence doesn't make sense: status codes 128-255 do have special purpose in UNIX systems.
    – user222973
    Commented Apr 2, 2016 at 21:43
  • 3
    Don't confuse Bash exit values (which are 0-127, 128+ being special Bash values) with program exit values (which are 0-255, see pubs.opengroup.org/onlinepubs/009695399/functions/exit.html). As for the size, remember that C programmers have been dealing with multiple word sizes (originally 12, 16, and 32 bits) since the beginning so we automatically try for idioms that don't require us to consider word size. Since Unix predates Posix by 2 decades there wasn't always the 8-bit limitation so we wrote so it didn't matter.
    – Todd Knarr
    Commented Apr 3, 2016 at 2:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.