What is the min and max values of exit codes in Linux?

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
30
down vote

favorite
6












What is the min and max values of the following exit codes in Linux:



  1. The exit code returned from a binary executable (for example: a C
    program).

  2. The exit code returned from a bash script (when calling exit).

  3. The exit code returned from a function (when calling return). I
    think this is between 0 and 255.






share|improve this question






















  • For part 3, do you mean returning from a shell function? That may depend on the shell, but I note that Bash's manual says "Exit statuses fall between 0 and 255" and "Exit statuses from shell builtins and compound commands are also limited to this range." return is, of course, a shell builtin.
    – Toby Speight
    Jan 24 at 13:33











  • Related (has answers to most of your questions): Default exit code when process is terminated?
    – Stéphane Chazelas
    Jan 24 at 15:32










  • @TobySpeight, that's a limitation of the bash shell. Some other shells like zsh can return any signed 32 bit value like for exit. Some like rc or es can return data of any of the types they support (scalar or list). See the linked Q&A for details.
    – Stéphane Chazelas
    Jan 24 at 15:36















up vote
30
down vote

favorite
6












What is the min and max values of the following exit codes in Linux:



  1. The exit code returned from a binary executable (for example: a C
    program).

  2. The exit code returned from a bash script (when calling exit).

  3. The exit code returned from a function (when calling return). I
    think this is between 0 and 255.






share|improve this question






















  • For part 3, do you mean returning from a shell function? That may depend on the shell, but I note that Bash's manual says "Exit statuses fall between 0 and 255" and "Exit statuses from shell builtins and compound commands are also limited to this range." return is, of course, a shell builtin.
    – Toby Speight
    Jan 24 at 13:33











  • Related (has answers to most of your questions): Default exit code when process is terminated?
    – Stéphane Chazelas
    Jan 24 at 15:32










  • @TobySpeight, that's a limitation of the bash shell. Some other shells like zsh can return any signed 32 bit value like for exit. Some like rc or es can return data of any of the types they support (scalar or list). See the linked Q&A for details.
    – Stéphane Chazelas
    Jan 24 at 15:36













up vote
30
down vote

favorite
6









up vote
30
down vote

favorite
6






6





What is the min and max values of the following exit codes in Linux:



  1. The exit code returned from a binary executable (for example: a C
    program).

  2. The exit code returned from a bash script (when calling exit).

  3. The exit code returned from a function (when calling return). I
    think this is between 0 and 255.






share|improve this question














What is the min and max values of the following exit codes in Linux:



  1. The exit code returned from a binary executable (for example: a C
    program).

  2. The exit code returned from a bash script (when calling exit).

  3. The exit code returned from a function (when calling return). I
    think this is between 0 and 255.








share|improve this question













share|improve this question




share|improve this question








edited Jan 22 at 9:57









Tomasz

8,04052560




8,04052560










asked Jan 22 at 7:59









user271801

15423




15423











  • For part 3, do you mean returning from a shell function? That may depend on the shell, but I note that Bash's manual says "Exit statuses fall between 0 and 255" and "Exit statuses from shell builtins and compound commands are also limited to this range." return is, of course, a shell builtin.
    – Toby Speight
    Jan 24 at 13:33











  • Related (has answers to most of your questions): Default exit code when process is terminated?
    – Stéphane Chazelas
    Jan 24 at 15:32










  • @TobySpeight, that's a limitation of the bash shell. Some other shells like zsh can return any signed 32 bit value like for exit. Some like rc or es can return data of any of the types they support (scalar or list). See the linked Q&A for details.
    – Stéphane Chazelas
    Jan 24 at 15:36

















  • For part 3, do you mean returning from a shell function? That may depend on the shell, but I note that Bash's manual says "Exit statuses fall between 0 and 255" and "Exit statuses from shell builtins and compound commands are also limited to this range." return is, of course, a shell builtin.
    – Toby Speight
    Jan 24 at 13:33











  • Related (has answers to most of your questions): Default exit code when process is terminated?
    – Stéphane Chazelas
    Jan 24 at 15:32










  • @TobySpeight, that's a limitation of the bash shell. Some other shells like zsh can return any signed 32 bit value like for exit. Some like rc or es can return data of any of the types they support (scalar or list). See the linked Q&A for details.
    – Stéphane Chazelas
    Jan 24 at 15:36
















For part 3, do you mean returning from a shell function? That may depend on the shell, but I note that Bash's manual says "Exit statuses fall between 0 and 255" and "Exit statuses from shell builtins and compound commands are also limited to this range." return is, of course, a shell builtin.
– Toby Speight
Jan 24 at 13:33





For part 3, do you mean returning from a shell function? That may depend on the shell, but I note that Bash's manual says "Exit statuses fall between 0 and 255" and "Exit statuses from shell builtins and compound commands are also limited to this range." return is, of course, a shell builtin.
– Toby Speight
Jan 24 at 13:33













Related (has answers to most of your questions): Default exit code when process is terminated?
– Stéphane Chazelas
Jan 24 at 15:32




Related (has answers to most of your questions): Default exit code when process is terminated?
– Stéphane Chazelas
Jan 24 at 15:32












@TobySpeight, that's a limitation of the bash shell. Some other shells like zsh can return any signed 32 bit value like for exit. Some like rc or es can return data of any of the types they support (scalar or list). See the linked Q&A for details.
– Stéphane Chazelas
Jan 24 at 15:36





@TobySpeight, that's a limitation of the bash shell. Some other shells like zsh can return any signed 32 bit value like for exit. Some like rc or es can return data of any of the types they support (scalar or list). See the linked Q&A for details.
– Stéphane Chazelas
Jan 24 at 15:36











4 Answers
4






active

oldest

votes

















up vote
62
down vote













The number passed to the _exit()/exit_group() system call (sometimes referred as the exit code to avoid the ambiguity with exit status which is also referring to an encoding of either the exit code or signal number and additional info depending on whether the process was killed or exited normally) is of type int, so on Unix-like systems like Linux, typically a 32bit integer with values from -2147483648 (-231) to 2147483647 (231-1).



However, on all systems, when the parent process (or the child subreaper or init if the parent died) uses the wait(), waitpid(), wait3(), wait4() system calls to retrieve it, only the lower 8 bits of it are available (values 0 to 255 (28-1)).



When using the waitid() API (or a signal handler on SIGCHLD), on most systems (and as POSIX now more clearly requires in the 2016 edition of the standard (see _exit() specification)), the full number is available (in the si_status field of the returned structure). That is not the case on Linux yet though which also truncates the number to 8 bits with the waitid() API, though that's likely to change in the future.



Generally, you'd want to only use values 0 (generally meaning success) to 125 only, as many shells use values above 128 in their $? representation of the exit status to encode the signal number of a process being killed and 126 and 127 for special conditions.



You may want to use 126 to 255 on exit() to mean the same thing as they do for the shell's $? (like when a script does ret=$?; ...; exit "$ret"). Using values outside 0 -> 255 is generally not useful. You'd generally only do that if you know the parent will use the waitid() API on systems that don't truncate and you happen to have a need for the 32bit range of values. Note that if you do a exit(2048) for instance, that will be seen as success by parents using the traditional wait*() APIs.



More info at:



  • Default exit code when process is terminated?

That Q&A should hopefully answer most of your other questions and clarify what is meant by exit status. I'll add a few more things:



A process cannot terminate unless it's killed or calls the _exit()/exit_group() system calls. When you return from main() in C, the libc calls that system call with the return value.



Most languages have a exit() function that wraps that system call, and the value they take, if any is generally passed as is to the system call. (note that those generally do more things like the clean-up done by C's exit() function that flushes the stdio buffers, runs the atexit() hooks...)



That's the case of at least:



$ strace -e exit_group awk 'BEGINexit(1234)'
exit_group(1234) = ?
$ strace -e exit_group mawk 'BEGINexit(1234)'
exit_group(1234) = ?
$ strace -e exit_group busybox awk 'BEGINexit(1234)'
exit_group(1234) = ?
$ echo | strace -e exit_group sed 'Q1234'
exit_group(1234) = ?
$ strace -e exit_group perl -e 'exit(1234)'
exit_group(1234) = ?
$ strace -e exit_group python -c 'exit(1234)'
exit_group(1234) = ?
$ strace -e exit_group expect -c 'exit 1234'
exit_group(1234) = ?
$ strace -e exit_group php -r 'exit(1234);'
exit_group(1234) = ?
$ strace -e exit_group zsh -c 'exit 1234'
exit_group(1234)


You occasionaly see some that complain when you use a value outside of 0-255:



$ echo 'm4exit(1234)' | strace -e exit_group m4
m4:stdin:1: exit status out of range: `1234'
exit_group(1) = ?


Some shells complain when you use a negative value:



$ strace -e exit_group dash -c 'exit -1234'
dash: 1: exit: Illegal number: -1234
exit_group(2) = ?
$ strace -e exit_group yash -c 'exit -- -1234'
exit: `-1234' is not a valid integer
exit_group(2) = ?


POSIX leaves the behaviour undefined if the value passed to the exit special builtin is outside 0->255.



Some shells show some unexpected behaviours if you do:




  • bash (and mksh but not pdksh on which it is based) takes upon itself to truncate the value to 8 bits:



    $ strace -e exit_group bash -c 'exit 1234'
    exit_group(210) = ?


    So in those shells, if you do want to exit with a value outside of 0-255, you have to do something like:



    exec zsh -c 'exit -- -12345'
    exec perl -e 'exit(-12345)'


    That is execute another command in the same process that can call the system call with the value you want.




  • as mentioned at that other Q&A, ksh93 has the weirdest behaviour for exit values from 257 to 256+max_signal_number where instead of calling exit_group(), it kills itself with the corresponding signal¹.



    $ ksh -c 'exit "$((256 + $(kill -l STOP)))"'
    zsh: suspended (signal) ksh -c 'exit "$((256 + $(kill -l STOP)))"'


    and otherwise truncates the number like bash/mksh.




¹ That's likely to change in the next version though. Now that the development of ksh93 has been taken over as a community effort outside of AT&T, that behaviour, even though encouraged somehow by POSIX, is being reverted






share|improve this answer


















  • 1




    Do you know if there's any discussion on implementing the full exit code in si_status for Linux?
    – Ruslan
    Jan 22 at 10:45






  • 2




    @Ruslan, not more than the austingroupbugs.net/view.php?id=594#c1318 (from Eric Blake (RedHat)) at the link I gave
    – Stéphane Chazelas
    Jan 22 at 10:56











  • "is of type int, so a 32bit integer". Linux really guarantees that an int will always be 32bit? Even when running on some of those tiny microcontrollers? That strikes me as really odd. POSIX certainly doesn't.
    – Voo
    Jan 24 at 8:10











  • @Voo, those tiny microcontrollers can't run Linux. While C requires int to be at least 16 bits, POSIX more or less requires it to be at least 32 bits and programming environments to have a uint32_t. I don't know if Linux supports any programming environment where ints are anything but 32bits, I've never come across any.
    – Stéphane Chazelas
    Jan 24 at 10:06










  • @Voo, (continued) there's nothing stopping a compiler to provide 32bit integers on your microcontroller with 16bit registers, but there are likely going to be many other things preventing this controller from running an OS like Linux, the fact that it has only a few kilobytes of memory for instance.
    – Stéphane Chazelas
    Jan 24 at 10:08

















up vote
10
down vote













The minimum is 0, and that's considered the success value. All the other ones are failure. The maximum is 255 also known as -1.



These rules apply for both scripts and other executables, as well as shell functions.



Bigger values result to modulo 256.






share|improve this answer


















  • 2




    To be precise, in some Bourne-like shells (but not bash or other most commonly used ones) the exit code passed to the exit builtin is not treated as modulo-256, and instead causes an error. (For example, the common exit -1 is actually not a portable equivalent to exit 255 in most shells). And whether exit(-1) at the C level is equivalent to exit(255) is a detail that is de-facto certain to work, but relies on implementation defined behavior (though this isn't a problem on modern systems you're likely to use in practice).
    – mtraceur
    Jan 23 at 18:35

















up vote
4
down vote













This looks so simple, but oh teh woes.



The C language (and following that most other languages directly or indirectly) requires that returning from main be equivalent to calling exit with the same argument as the return value. This is an integer (the return type is very clearly int), so in principle the range would be INT_MIN to INT_MAX.



However, POSIX states that only the lowermost 8 bits passed to exit shall be made available to a waiting parent process, literally as if it was "status & 0xFF".

So, in practice, the exit code is a (still signed) integer of which only the lowest 8 bits are set.



The minimum will thus be -128, and the maximum 127. Hang on, that's not true. It will be 0 to 255.



But alas, of course it cannot be that simple. In practice, Linux (or rather bash) does it differently. The valid range of return codes is 0 to 255 (i.e. unsigned).



To be on the safe side in terms of avoiding confusion, it's probably a good idea to just assume that return codes are unsigned, and cast anything you get back from wait to unsigned. That way it's consistent with what you see in a shell. Since the topmost bits (including the most significant one) are cleared out, that's not even "wrong" because although technically signed, the actual values are always unsigned (since the sign bit is never set).

It also helps avoiding the common error of comparing an exit code to -1, which for some strange reason never seems to appear even when a program exits with -1 (well, guess why!).



About your last point, returning from a function, if this function happens to be main, then see above. Otherwise, it depends on what the function's return type is, it could in principle be anything (including void).






share|improve this answer





























    up vote
    2
    down vote














    1. The exit code returned from a binary executable (for example: a C program).

    2. The exit code returned from a bash script (when calling exit).



    Exit codes from any process -- whether it's a binary executable, a shell script, or anything else -- range from 0 to 255. It's possible to pass a larger value to exit(), but only the lower 8 bits of the status are made available to other processes through wait().




    1. The exit code returned from a function (when calling return). I think this is between 0 and 255.



    A C function can be declared as returning almost any type. The limits of its return value are determined entirely by that type: for instance, -128 to 127 for a function returning signed char, or 0 to 4.2 billion for a function returning unsigned int, or any floating-point number up to and including inf for a function returning double. And that isn't counting the non-numeric types, like void * or a struct...






    share|improve this answer




















      Your Answer







      StackExchange.ready(function()
      var channelOptions =
      tags: "".split(" "),
      id: "106"
      ;
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function()
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled)
      StackExchange.using("snippets", function()
      createEditor();
      );

      else
      createEditor();

      );

      function createEditor()
      StackExchange.prepareEditor(
      heartbeatType: 'answer',
      convertImagesToLinks: false,
      noModals: false,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: null,
      bindNavPrevention: true,
      postfix: "",
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      );



      );








       

      draft saved


      draft discarded


















      StackExchange.ready(
      function ()
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f418784%2fwhat-is-the-min-and-max-values-of-exit-codes-in-linux%23new-answer', 'question_page');

      );

      Post as a guest






























      4 Answers
      4






      active

      oldest

      votes








      4 Answers
      4






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes








      up vote
      62
      down vote













      The number passed to the _exit()/exit_group() system call (sometimes referred as the exit code to avoid the ambiguity with exit status which is also referring to an encoding of either the exit code or signal number and additional info depending on whether the process was killed or exited normally) is of type int, so on Unix-like systems like Linux, typically a 32bit integer with values from -2147483648 (-231) to 2147483647 (231-1).



      However, on all systems, when the parent process (or the child subreaper or init if the parent died) uses the wait(), waitpid(), wait3(), wait4() system calls to retrieve it, only the lower 8 bits of it are available (values 0 to 255 (28-1)).



      When using the waitid() API (or a signal handler on SIGCHLD), on most systems (and as POSIX now more clearly requires in the 2016 edition of the standard (see _exit() specification)), the full number is available (in the si_status field of the returned structure). That is not the case on Linux yet though which also truncates the number to 8 bits with the waitid() API, though that's likely to change in the future.



      Generally, you'd want to only use values 0 (generally meaning success) to 125 only, as many shells use values above 128 in their $? representation of the exit status to encode the signal number of a process being killed and 126 and 127 for special conditions.



      You may want to use 126 to 255 on exit() to mean the same thing as they do for the shell's $? (like when a script does ret=$?; ...; exit "$ret"). Using values outside 0 -> 255 is generally not useful. You'd generally only do that if you know the parent will use the waitid() API on systems that don't truncate and you happen to have a need for the 32bit range of values. Note that if you do a exit(2048) for instance, that will be seen as success by parents using the traditional wait*() APIs.



      More info at:



      • Default exit code when process is terminated?

      That Q&A should hopefully answer most of your other questions and clarify what is meant by exit status. I'll add a few more things:



      A process cannot terminate unless it's killed or calls the _exit()/exit_group() system calls. When you return from main() in C, the libc calls that system call with the return value.



      Most languages have a exit() function that wraps that system call, and the value they take, if any is generally passed as is to the system call. (note that those generally do more things like the clean-up done by C's exit() function that flushes the stdio buffers, runs the atexit() hooks...)



      That's the case of at least:



      $ strace -e exit_group awk 'BEGINexit(1234)'
      exit_group(1234) = ?
      $ strace -e exit_group mawk 'BEGINexit(1234)'
      exit_group(1234) = ?
      $ strace -e exit_group busybox awk 'BEGINexit(1234)'
      exit_group(1234) = ?
      $ echo | strace -e exit_group sed 'Q1234'
      exit_group(1234) = ?
      $ strace -e exit_group perl -e 'exit(1234)'
      exit_group(1234) = ?
      $ strace -e exit_group python -c 'exit(1234)'
      exit_group(1234) = ?
      $ strace -e exit_group expect -c 'exit 1234'
      exit_group(1234) = ?
      $ strace -e exit_group php -r 'exit(1234);'
      exit_group(1234) = ?
      $ strace -e exit_group zsh -c 'exit 1234'
      exit_group(1234)


      You occasionaly see some that complain when you use a value outside of 0-255:



      $ echo 'm4exit(1234)' | strace -e exit_group m4
      m4:stdin:1: exit status out of range: `1234'
      exit_group(1) = ?


      Some shells complain when you use a negative value:



      $ strace -e exit_group dash -c 'exit -1234'
      dash: 1: exit: Illegal number: -1234
      exit_group(2) = ?
      $ strace -e exit_group yash -c 'exit -- -1234'
      exit: `-1234' is not a valid integer
      exit_group(2) = ?


      POSIX leaves the behaviour undefined if the value passed to the exit special builtin is outside 0->255.



      Some shells show some unexpected behaviours if you do:




      • bash (and mksh but not pdksh on which it is based) takes upon itself to truncate the value to 8 bits:



        $ strace -e exit_group bash -c 'exit 1234'
        exit_group(210) = ?


        So in those shells, if you do want to exit with a value outside of 0-255, you have to do something like:



        exec zsh -c 'exit -- -12345'
        exec perl -e 'exit(-12345)'


        That is execute another command in the same process that can call the system call with the value you want.




      • as mentioned at that other Q&A, ksh93 has the weirdest behaviour for exit values from 257 to 256+max_signal_number where instead of calling exit_group(), it kills itself with the corresponding signal¹.



        $ ksh -c 'exit "$((256 + $(kill -l STOP)))"'
        zsh: suspended (signal) ksh -c 'exit "$((256 + $(kill -l STOP)))"'


        and otherwise truncates the number like bash/mksh.




      ¹ That's likely to change in the next version though. Now that the development of ksh93 has been taken over as a community effort outside of AT&T, that behaviour, even though encouraged somehow by POSIX, is being reverted






      share|improve this answer


















      • 1




        Do you know if there's any discussion on implementing the full exit code in si_status for Linux?
        – Ruslan
        Jan 22 at 10:45






      • 2




        @Ruslan, not more than the austingroupbugs.net/view.php?id=594#c1318 (from Eric Blake (RedHat)) at the link I gave
        – Stéphane Chazelas
        Jan 22 at 10:56











      • "is of type int, so a 32bit integer". Linux really guarantees that an int will always be 32bit? Even when running on some of those tiny microcontrollers? That strikes me as really odd. POSIX certainly doesn't.
        – Voo
        Jan 24 at 8:10











      • @Voo, those tiny microcontrollers can't run Linux. While C requires int to be at least 16 bits, POSIX more or less requires it to be at least 32 bits and programming environments to have a uint32_t. I don't know if Linux supports any programming environment where ints are anything but 32bits, I've never come across any.
        – Stéphane Chazelas
        Jan 24 at 10:06










      • @Voo, (continued) there's nothing stopping a compiler to provide 32bit integers on your microcontroller with 16bit registers, but there are likely going to be many other things preventing this controller from running an OS like Linux, the fact that it has only a few kilobytes of memory for instance.
        – Stéphane Chazelas
        Jan 24 at 10:08














      up vote
      62
      down vote













      The number passed to the _exit()/exit_group() system call (sometimes referred as the exit code to avoid the ambiguity with exit status which is also referring to an encoding of either the exit code or signal number and additional info depending on whether the process was killed or exited normally) is of type int, so on Unix-like systems like Linux, typically a 32bit integer with values from -2147483648 (-231) to 2147483647 (231-1).



      However, on all systems, when the parent process (or the child subreaper or init if the parent died) uses the wait(), waitpid(), wait3(), wait4() system calls to retrieve it, only the lower 8 bits of it are available (values 0 to 255 (28-1)).



      When using the waitid() API (or a signal handler on SIGCHLD), on most systems (and as POSIX now more clearly requires in the 2016 edition of the standard (see _exit() specification)), the full number is available (in the si_status field of the returned structure). That is not the case on Linux yet though which also truncates the number to 8 bits with the waitid() API, though that's likely to change in the future.



      Generally, you'd want to only use values 0 (generally meaning success) to 125 only, as many shells use values above 128 in their $? representation of the exit status to encode the signal number of a process being killed and 126 and 127 for special conditions.



      You may want to use 126 to 255 on exit() to mean the same thing as they do for the shell's $? (like when a script does ret=$?; ...; exit "$ret"). Using values outside 0 -> 255 is generally not useful. You'd generally only do that if you know the parent will use the waitid() API on systems that don't truncate and you happen to have a need for the 32bit range of values. Note that if you do a exit(2048) for instance, that will be seen as success by parents using the traditional wait*() APIs.



      More info at:



      • Default exit code when process is terminated?

      That Q&A should hopefully answer most of your other questions and clarify what is meant by exit status. I'll add a few more things:



      A process cannot terminate unless it's killed or calls the _exit()/exit_group() system calls. When you return from main() in C, the libc calls that system call with the return value.



      Most languages have a exit() function that wraps that system call, and the value they take, if any is generally passed as is to the system call. (note that those generally do more things like the clean-up done by C's exit() function that flushes the stdio buffers, runs the atexit() hooks...)



      That's the case of at least:



      $ strace -e exit_group awk 'BEGINexit(1234)'
      exit_group(1234) = ?
      $ strace -e exit_group mawk 'BEGINexit(1234)'
      exit_group(1234) = ?
      $ strace -e exit_group busybox awk 'BEGINexit(1234)'
      exit_group(1234) = ?
      $ echo | strace -e exit_group sed 'Q1234'
      exit_group(1234) = ?
      $ strace -e exit_group perl -e 'exit(1234)'
      exit_group(1234) = ?
      $ strace -e exit_group python -c 'exit(1234)'
      exit_group(1234) = ?
      $ strace -e exit_group expect -c 'exit 1234'
      exit_group(1234) = ?
      $ strace -e exit_group php -r 'exit(1234);'
      exit_group(1234) = ?
      $ strace -e exit_group zsh -c 'exit 1234'
      exit_group(1234)


      You occasionaly see some that complain when you use a value outside of 0-255:



      $ echo 'm4exit(1234)' | strace -e exit_group m4
      m4:stdin:1: exit status out of range: `1234'
      exit_group(1) = ?


      Some shells complain when you use a negative value:



      $ strace -e exit_group dash -c 'exit -1234'
      dash: 1: exit: Illegal number: -1234
      exit_group(2) = ?
      $ strace -e exit_group yash -c 'exit -- -1234'
      exit: `-1234' is not a valid integer
      exit_group(2) = ?


      POSIX leaves the behaviour undefined if the value passed to the exit special builtin is outside 0->255.



      Some shells show some unexpected behaviours if you do:




      • bash (and mksh but not pdksh on which it is based) takes upon itself to truncate the value to 8 bits:



        $ strace -e exit_group bash -c 'exit 1234'
        exit_group(210) = ?


        So in those shells, if you do want to exit with a value outside of 0-255, you have to do something like:



        exec zsh -c 'exit -- -12345'
        exec perl -e 'exit(-12345)'


        That is execute another command in the same process that can call the system call with the value you want.




      • as mentioned at that other Q&A, ksh93 has the weirdest behaviour for exit values from 257 to 256+max_signal_number where instead of calling exit_group(), it kills itself with the corresponding signal¹.



        $ ksh -c 'exit "$((256 + $(kill -l STOP)))"'
        zsh: suspended (signal) ksh -c 'exit "$((256 + $(kill -l STOP)))"'


        and otherwise truncates the number like bash/mksh.




      ¹ That's likely to change in the next version though. Now that the development of ksh93 has been taken over as a community effort outside of AT&T, that behaviour, even though encouraged somehow by POSIX, is being reverted






      share|improve this answer


















      • 1




        Do you know if there's any discussion on implementing the full exit code in si_status for Linux?
        – Ruslan
        Jan 22 at 10:45






      • 2




        @Ruslan, not more than the austingroupbugs.net/view.php?id=594#c1318 (from Eric Blake (RedHat)) at the link I gave
        – Stéphane Chazelas
        Jan 22 at 10:56











      • "is of type int, so a 32bit integer". Linux really guarantees that an int will always be 32bit? Even when running on some of those tiny microcontrollers? That strikes me as really odd. POSIX certainly doesn't.
        – Voo
        Jan 24 at 8:10











      • @Voo, those tiny microcontrollers can't run Linux. While C requires int to be at least 16 bits, POSIX more or less requires it to be at least 32 bits and programming environments to have a uint32_t. I don't know if Linux supports any programming environment where ints are anything but 32bits, I've never come across any.
        – Stéphane Chazelas
        Jan 24 at 10:06










      • @Voo, (continued) there's nothing stopping a compiler to provide 32bit integers on your microcontroller with 16bit registers, but there are likely going to be many other things preventing this controller from running an OS like Linux, the fact that it has only a few kilobytes of memory for instance.
        – Stéphane Chazelas
        Jan 24 at 10:08












      up vote
      62
      down vote










      up vote
      62
      down vote









      The number passed to the _exit()/exit_group() system call (sometimes referred as the exit code to avoid the ambiguity with exit status which is also referring to an encoding of either the exit code or signal number and additional info depending on whether the process was killed or exited normally) is of type int, so on Unix-like systems like Linux, typically a 32bit integer with values from -2147483648 (-231) to 2147483647 (231-1).



      However, on all systems, when the parent process (or the child subreaper or init if the parent died) uses the wait(), waitpid(), wait3(), wait4() system calls to retrieve it, only the lower 8 bits of it are available (values 0 to 255 (28-1)).



      When using the waitid() API (or a signal handler on SIGCHLD), on most systems (and as POSIX now more clearly requires in the 2016 edition of the standard (see _exit() specification)), the full number is available (in the si_status field of the returned structure). That is not the case on Linux yet though which also truncates the number to 8 bits with the waitid() API, though that's likely to change in the future.



      Generally, you'd want to only use values 0 (generally meaning success) to 125 only, as many shells use values above 128 in their $? representation of the exit status to encode the signal number of a process being killed and 126 and 127 for special conditions.



      You may want to use 126 to 255 on exit() to mean the same thing as they do for the shell's $? (like when a script does ret=$?; ...; exit "$ret"). Using values outside 0 -> 255 is generally not useful. You'd generally only do that if you know the parent will use the waitid() API on systems that don't truncate and you happen to have a need for the 32bit range of values. Note that if you do a exit(2048) for instance, that will be seen as success by parents using the traditional wait*() APIs.



      More info at:



      • Default exit code when process is terminated?

      That Q&A should hopefully answer most of your other questions and clarify what is meant by exit status. I'll add a few more things:



      A process cannot terminate unless it's killed or calls the _exit()/exit_group() system calls. When you return from main() in C, the libc calls that system call with the return value.



      Most languages have a exit() function that wraps that system call, and the value they take, if any is generally passed as is to the system call. (note that those generally do more things like the clean-up done by C's exit() function that flushes the stdio buffers, runs the atexit() hooks...)



      That's the case of at least:



      $ strace -e exit_group awk 'BEGINexit(1234)'
      exit_group(1234) = ?
      $ strace -e exit_group mawk 'BEGINexit(1234)'
      exit_group(1234) = ?
      $ strace -e exit_group busybox awk 'BEGINexit(1234)'
      exit_group(1234) = ?
      $ echo | strace -e exit_group sed 'Q1234'
      exit_group(1234) = ?
      $ strace -e exit_group perl -e 'exit(1234)'
      exit_group(1234) = ?
      $ strace -e exit_group python -c 'exit(1234)'
      exit_group(1234) = ?
      $ strace -e exit_group expect -c 'exit 1234'
      exit_group(1234) = ?
      $ strace -e exit_group php -r 'exit(1234);'
      exit_group(1234) = ?
      $ strace -e exit_group zsh -c 'exit 1234'
      exit_group(1234)


      You occasionaly see some that complain when you use a value outside of 0-255:



      $ echo 'm4exit(1234)' | strace -e exit_group m4
      m4:stdin:1: exit status out of range: `1234'
      exit_group(1) = ?


      Some shells complain when you use a negative value:



      $ strace -e exit_group dash -c 'exit -1234'
      dash: 1: exit: Illegal number: -1234
      exit_group(2) = ?
      $ strace -e exit_group yash -c 'exit -- -1234'
      exit: `-1234' is not a valid integer
      exit_group(2) = ?


      POSIX leaves the behaviour undefined if the value passed to the exit special builtin is outside 0->255.



      Some shells show some unexpected behaviours if you do:




      • bash (and mksh but not pdksh on which it is based) takes upon itself to truncate the value to 8 bits:



        $ strace -e exit_group bash -c 'exit 1234'
        exit_group(210) = ?


        So in those shells, if you do want to exit with a value outside of 0-255, you have to do something like:



        exec zsh -c 'exit -- -12345'
        exec perl -e 'exit(-12345)'


        That is execute another command in the same process that can call the system call with the value you want.




      • as mentioned at that other Q&A, ksh93 has the weirdest behaviour for exit values from 257 to 256+max_signal_number where instead of calling exit_group(), it kills itself with the corresponding signal¹.



        $ ksh -c 'exit "$((256 + $(kill -l STOP)))"'
        zsh: suspended (signal) ksh -c 'exit "$((256 + $(kill -l STOP)))"'


        and otherwise truncates the number like bash/mksh.




      ¹ That's likely to change in the next version though. Now that the development of ksh93 has been taken over as a community effort outside of AT&T, that behaviour, even though encouraged somehow by POSIX, is being reverted






      share|improve this answer














      The number passed to the _exit()/exit_group() system call (sometimes referred as the exit code to avoid the ambiguity with exit status which is also referring to an encoding of either the exit code or signal number and additional info depending on whether the process was killed or exited normally) is of type int, so on Unix-like systems like Linux, typically a 32bit integer with values from -2147483648 (-231) to 2147483647 (231-1).



      However, on all systems, when the parent process (or the child subreaper or init if the parent died) uses the wait(), waitpid(), wait3(), wait4() system calls to retrieve it, only the lower 8 bits of it are available (values 0 to 255 (28-1)).



      When using the waitid() API (or a signal handler on SIGCHLD), on most systems (and as POSIX now more clearly requires in the 2016 edition of the standard (see _exit() specification)), the full number is available (in the si_status field of the returned structure). That is not the case on Linux yet though which also truncates the number to 8 bits with the waitid() API, though that's likely to change in the future.



      Generally, you'd want to only use values 0 (generally meaning success) to 125 only, as many shells use values above 128 in their $? representation of the exit status to encode the signal number of a process being killed and 126 and 127 for special conditions.



      You may want to use 126 to 255 on exit() to mean the same thing as they do for the shell's $? (like when a script does ret=$?; ...; exit "$ret"). Using values outside 0 -> 255 is generally not useful. You'd generally only do that if you know the parent will use the waitid() API on systems that don't truncate and you happen to have a need for the 32bit range of values. Note that if you do a exit(2048) for instance, that will be seen as success by parents using the traditional wait*() APIs.



      More info at:



      • Default exit code when process is terminated?

      That Q&A should hopefully answer most of your other questions and clarify what is meant by exit status. I'll add a few more things:



      A process cannot terminate unless it's killed or calls the _exit()/exit_group() system calls. When you return from main() in C, the libc calls that system call with the return value.



      Most languages have a exit() function that wraps that system call, and the value they take, if any is generally passed as is to the system call. (note that those generally do more things like the clean-up done by C's exit() function that flushes the stdio buffers, runs the atexit() hooks...)



      That's the case of at least:



      $ strace -e exit_group awk 'BEGINexit(1234)'
      exit_group(1234) = ?
      $ strace -e exit_group mawk 'BEGINexit(1234)'
      exit_group(1234) = ?
      $ strace -e exit_group busybox awk 'BEGINexit(1234)'
      exit_group(1234) = ?
      $ echo | strace -e exit_group sed 'Q1234'
      exit_group(1234) = ?
      $ strace -e exit_group perl -e 'exit(1234)'
      exit_group(1234) = ?
      $ strace -e exit_group python -c 'exit(1234)'
      exit_group(1234) = ?
      $ strace -e exit_group expect -c 'exit 1234'
      exit_group(1234) = ?
      $ strace -e exit_group php -r 'exit(1234);'
      exit_group(1234) = ?
      $ strace -e exit_group zsh -c 'exit 1234'
      exit_group(1234)


      You occasionaly see some that complain when you use a value outside of 0-255:



      $ echo 'm4exit(1234)' | strace -e exit_group m4
      m4:stdin:1: exit status out of range: `1234'
      exit_group(1) = ?


      Some shells complain when you use a negative value:



      $ strace -e exit_group dash -c 'exit -1234'
      dash: 1: exit: Illegal number: -1234
      exit_group(2) = ?
      $ strace -e exit_group yash -c 'exit -- -1234'
      exit: `-1234' is not a valid integer
      exit_group(2) = ?


      POSIX leaves the behaviour undefined if the value passed to the exit special builtin is outside 0->255.



      Some shells show some unexpected behaviours if you do:




      • bash (and mksh but not pdksh on which it is based) takes upon itself to truncate the value to 8 bits:



        $ strace -e exit_group bash -c 'exit 1234'
        exit_group(210) = ?


        So in those shells, if you do want to exit with a value outside of 0-255, you have to do something like:



        exec zsh -c 'exit -- -12345'
        exec perl -e 'exit(-12345)'


        That is execute another command in the same process that can call the system call with the value you want.




      • as mentioned at that other Q&A, ksh93 has the weirdest behaviour for exit values from 257 to 256+max_signal_number where instead of calling exit_group(), it kills itself with the corresponding signal¹.



        $ ksh -c 'exit "$((256 + $(kill -l STOP)))"'
        zsh: suspended (signal) ksh -c 'exit "$((256 + $(kill -l STOP)))"'


        and otherwise truncates the number like bash/mksh.




      ¹ That's likely to change in the next version though. Now that the development of ksh93 has been taken over as a community effort outside of AT&T, that behaviour, even though encouraged somehow by POSIX, is being reverted







      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited Jan 24 at 11:13

























      answered Jan 22 at 9:35









      Stéphane Chazelas

      281k53518849




      281k53518849







      • 1




        Do you know if there's any discussion on implementing the full exit code in si_status for Linux?
        – Ruslan
        Jan 22 at 10:45






      • 2




        @Ruslan, not more than the austingroupbugs.net/view.php?id=594#c1318 (from Eric Blake (RedHat)) at the link I gave
        – Stéphane Chazelas
        Jan 22 at 10:56











      • "is of type int, so a 32bit integer". Linux really guarantees that an int will always be 32bit? Even when running on some of those tiny microcontrollers? That strikes me as really odd. POSIX certainly doesn't.
        – Voo
        Jan 24 at 8:10











      • @Voo, those tiny microcontrollers can't run Linux. While C requires int to be at least 16 bits, POSIX more or less requires it to be at least 32 bits and programming environments to have a uint32_t. I don't know if Linux supports any programming environment where ints are anything but 32bits, I've never come across any.
        – Stéphane Chazelas
        Jan 24 at 10:06










      • @Voo, (continued) there's nothing stopping a compiler to provide 32bit integers on your microcontroller with 16bit registers, but there are likely going to be many other things preventing this controller from running an OS like Linux, the fact that it has only a few kilobytes of memory for instance.
        – Stéphane Chazelas
        Jan 24 at 10:08












      • 1




        Do you know if there's any discussion on implementing the full exit code in si_status for Linux?
        – Ruslan
        Jan 22 at 10:45






      • 2




        @Ruslan, not more than the austingroupbugs.net/view.php?id=594#c1318 (from Eric Blake (RedHat)) at the link I gave
        – Stéphane Chazelas
        Jan 22 at 10:56











      • "is of type int, so a 32bit integer". Linux really guarantees that an int will always be 32bit? Even when running on some of those tiny microcontrollers? That strikes me as really odd. POSIX certainly doesn't.
        – Voo
        Jan 24 at 8:10











      • @Voo, those tiny microcontrollers can't run Linux. While C requires int to be at least 16 bits, POSIX more or less requires it to be at least 32 bits and programming environments to have a uint32_t. I don't know if Linux supports any programming environment where ints are anything but 32bits, I've never come across any.
        – Stéphane Chazelas
        Jan 24 at 10:06










      • @Voo, (continued) there's nothing stopping a compiler to provide 32bit integers on your microcontroller with 16bit registers, but there are likely going to be many other things preventing this controller from running an OS like Linux, the fact that it has only a few kilobytes of memory for instance.
        – Stéphane Chazelas
        Jan 24 at 10:08







      1




      1




      Do you know if there's any discussion on implementing the full exit code in si_status for Linux?
      – Ruslan
      Jan 22 at 10:45




      Do you know if there's any discussion on implementing the full exit code in si_status for Linux?
      – Ruslan
      Jan 22 at 10:45




      2




      2




      @Ruslan, not more than the austingroupbugs.net/view.php?id=594#c1318 (from Eric Blake (RedHat)) at the link I gave
      – Stéphane Chazelas
      Jan 22 at 10:56





      @Ruslan, not more than the austingroupbugs.net/view.php?id=594#c1318 (from Eric Blake (RedHat)) at the link I gave
      – Stéphane Chazelas
      Jan 22 at 10:56













      "is of type int, so a 32bit integer". Linux really guarantees that an int will always be 32bit? Even when running on some of those tiny microcontrollers? That strikes me as really odd. POSIX certainly doesn't.
      – Voo
      Jan 24 at 8:10





      "is of type int, so a 32bit integer". Linux really guarantees that an int will always be 32bit? Even when running on some of those tiny microcontrollers? That strikes me as really odd. POSIX certainly doesn't.
      – Voo
      Jan 24 at 8:10













      @Voo, those tiny microcontrollers can't run Linux. While C requires int to be at least 16 bits, POSIX more or less requires it to be at least 32 bits and programming environments to have a uint32_t. I don't know if Linux supports any programming environment where ints are anything but 32bits, I've never come across any.
      – Stéphane Chazelas
      Jan 24 at 10:06




      @Voo, those tiny microcontrollers can't run Linux. While C requires int to be at least 16 bits, POSIX more or less requires it to be at least 32 bits and programming environments to have a uint32_t. I don't know if Linux supports any programming environment where ints are anything but 32bits, I've never come across any.
      – Stéphane Chazelas
      Jan 24 at 10:06












      @Voo, (continued) there's nothing stopping a compiler to provide 32bit integers on your microcontroller with 16bit registers, but there are likely going to be many other things preventing this controller from running an OS like Linux, the fact that it has only a few kilobytes of memory for instance.
      – Stéphane Chazelas
      Jan 24 at 10:08




      @Voo, (continued) there's nothing stopping a compiler to provide 32bit integers on your microcontroller with 16bit registers, but there are likely going to be many other things preventing this controller from running an OS like Linux, the fact that it has only a few kilobytes of memory for instance.
      – Stéphane Chazelas
      Jan 24 at 10:08












      up vote
      10
      down vote













      The minimum is 0, and that's considered the success value. All the other ones are failure. The maximum is 255 also known as -1.



      These rules apply for both scripts and other executables, as well as shell functions.



      Bigger values result to modulo 256.






      share|improve this answer


















      • 2




        To be precise, in some Bourne-like shells (but not bash or other most commonly used ones) the exit code passed to the exit builtin is not treated as modulo-256, and instead causes an error. (For example, the common exit -1 is actually not a portable equivalent to exit 255 in most shells). And whether exit(-1) at the C level is equivalent to exit(255) is a detail that is de-facto certain to work, but relies on implementation defined behavior (though this isn't a problem on modern systems you're likely to use in practice).
        – mtraceur
        Jan 23 at 18:35














      up vote
      10
      down vote













      The minimum is 0, and that's considered the success value. All the other ones are failure. The maximum is 255 also known as -1.



      These rules apply for both scripts and other executables, as well as shell functions.



      Bigger values result to modulo 256.






      share|improve this answer


















      • 2




        To be precise, in some Bourne-like shells (but not bash or other most commonly used ones) the exit code passed to the exit builtin is not treated as modulo-256, and instead causes an error. (For example, the common exit -1 is actually not a portable equivalent to exit 255 in most shells). And whether exit(-1) at the C level is equivalent to exit(255) is a detail that is de-facto certain to work, but relies on implementation defined behavior (though this isn't a problem on modern systems you're likely to use in practice).
        – mtraceur
        Jan 23 at 18:35












      up vote
      10
      down vote










      up vote
      10
      down vote









      The minimum is 0, and that's considered the success value. All the other ones are failure. The maximum is 255 also known as -1.



      These rules apply for both scripts and other executables, as well as shell functions.



      Bigger values result to modulo 256.






      share|improve this answer














      The minimum is 0, and that's considered the success value. All the other ones are failure. The maximum is 255 also known as -1.



      These rules apply for both scripts and other executables, as well as shell functions.



      Bigger values result to modulo 256.







      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited Jan 22 at 8:15

























      answered Jan 22 at 8:07









      Tomasz

      8,04052560




      8,04052560







      • 2




        To be precise, in some Bourne-like shells (but not bash or other most commonly used ones) the exit code passed to the exit builtin is not treated as modulo-256, and instead causes an error. (For example, the common exit -1 is actually not a portable equivalent to exit 255 in most shells). And whether exit(-1) at the C level is equivalent to exit(255) is a detail that is de-facto certain to work, but relies on implementation defined behavior (though this isn't a problem on modern systems you're likely to use in practice).
        – mtraceur
        Jan 23 at 18:35












      • 2




        To be precise, in some Bourne-like shells (but not bash or other most commonly used ones) the exit code passed to the exit builtin is not treated as modulo-256, and instead causes an error. (For example, the common exit -1 is actually not a portable equivalent to exit 255 in most shells). And whether exit(-1) at the C level is equivalent to exit(255) is a detail that is de-facto certain to work, but relies on implementation defined behavior (though this isn't a problem on modern systems you're likely to use in practice).
        – mtraceur
        Jan 23 at 18:35







      2




      2




      To be precise, in some Bourne-like shells (but not bash or other most commonly used ones) the exit code passed to the exit builtin is not treated as modulo-256, and instead causes an error. (For example, the common exit -1 is actually not a portable equivalent to exit 255 in most shells). And whether exit(-1) at the C level is equivalent to exit(255) is a detail that is de-facto certain to work, but relies on implementation defined behavior (though this isn't a problem on modern systems you're likely to use in practice).
      – mtraceur
      Jan 23 at 18:35




      To be precise, in some Bourne-like shells (but not bash or other most commonly used ones) the exit code passed to the exit builtin is not treated as modulo-256, and instead causes an error. (For example, the common exit -1 is actually not a portable equivalent to exit 255 in most shells). And whether exit(-1) at the C level is equivalent to exit(255) is a detail that is de-facto certain to work, but relies on implementation defined behavior (though this isn't a problem on modern systems you're likely to use in practice).
      – mtraceur
      Jan 23 at 18:35










      up vote
      4
      down vote













      This looks so simple, but oh teh woes.



      The C language (and following that most other languages directly or indirectly) requires that returning from main be equivalent to calling exit with the same argument as the return value. This is an integer (the return type is very clearly int), so in principle the range would be INT_MIN to INT_MAX.



      However, POSIX states that only the lowermost 8 bits passed to exit shall be made available to a waiting parent process, literally as if it was "status & 0xFF".

      So, in practice, the exit code is a (still signed) integer of which only the lowest 8 bits are set.



      The minimum will thus be -128, and the maximum 127. Hang on, that's not true. It will be 0 to 255.



      But alas, of course it cannot be that simple. In practice, Linux (or rather bash) does it differently. The valid range of return codes is 0 to 255 (i.e. unsigned).



      To be on the safe side in terms of avoiding confusion, it's probably a good idea to just assume that return codes are unsigned, and cast anything you get back from wait to unsigned. That way it's consistent with what you see in a shell. Since the topmost bits (including the most significant one) are cleared out, that's not even "wrong" because although technically signed, the actual values are always unsigned (since the sign bit is never set).

      It also helps avoiding the common error of comparing an exit code to -1, which for some strange reason never seems to appear even when a program exits with -1 (well, guess why!).



      About your last point, returning from a function, if this function happens to be main, then see above. Otherwise, it depends on what the function's return type is, it could in principle be anything (including void).






      share|improve this answer


























        up vote
        4
        down vote













        This looks so simple, but oh teh woes.



        The C language (and following that most other languages directly or indirectly) requires that returning from main be equivalent to calling exit with the same argument as the return value. This is an integer (the return type is very clearly int), so in principle the range would be INT_MIN to INT_MAX.



        However, POSIX states that only the lowermost 8 bits passed to exit shall be made available to a waiting parent process, literally as if it was "status & 0xFF".

        So, in practice, the exit code is a (still signed) integer of which only the lowest 8 bits are set.



        The minimum will thus be -128, and the maximum 127. Hang on, that's not true. It will be 0 to 255.



        But alas, of course it cannot be that simple. In practice, Linux (or rather bash) does it differently. The valid range of return codes is 0 to 255 (i.e. unsigned).



        To be on the safe side in terms of avoiding confusion, it's probably a good idea to just assume that return codes are unsigned, and cast anything you get back from wait to unsigned. That way it's consistent with what you see in a shell. Since the topmost bits (including the most significant one) are cleared out, that's not even "wrong" because although technically signed, the actual values are always unsigned (since the sign bit is never set).

        It also helps avoiding the common error of comparing an exit code to -1, which for some strange reason never seems to appear even when a program exits with -1 (well, guess why!).



        About your last point, returning from a function, if this function happens to be main, then see above. Otherwise, it depends on what the function's return type is, it could in principle be anything (including void).






        share|improve this answer
























          up vote
          4
          down vote










          up vote
          4
          down vote









          This looks so simple, but oh teh woes.



          The C language (and following that most other languages directly or indirectly) requires that returning from main be equivalent to calling exit with the same argument as the return value. This is an integer (the return type is very clearly int), so in principle the range would be INT_MIN to INT_MAX.



          However, POSIX states that only the lowermost 8 bits passed to exit shall be made available to a waiting parent process, literally as if it was "status & 0xFF".

          So, in practice, the exit code is a (still signed) integer of which only the lowest 8 bits are set.



          The minimum will thus be -128, and the maximum 127. Hang on, that's not true. It will be 0 to 255.



          But alas, of course it cannot be that simple. In practice, Linux (or rather bash) does it differently. The valid range of return codes is 0 to 255 (i.e. unsigned).



          To be on the safe side in terms of avoiding confusion, it's probably a good idea to just assume that return codes are unsigned, and cast anything you get back from wait to unsigned. That way it's consistent with what you see in a shell. Since the topmost bits (including the most significant one) are cleared out, that's not even "wrong" because although technically signed, the actual values are always unsigned (since the sign bit is never set).

          It also helps avoiding the common error of comparing an exit code to -1, which for some strange reason never seems to appear even when a program exits with -1 (well, guess why!).



          About your last point, returning from a function, if this function happens to be main, then see above. Otherwise, it depends on what the function's return type is, it could in principle be anything (including void).






          share|improve this answer














          This looks so simple, but oh teh woes.



          The C language (and following that most other languages directly or indirectly) requires that returning from main be equivalent to calling exit with the same argument as the return value. This is an integer (the return type is very clearly int), so in principle the range would be INT_MIN to INT_MAX.



          However, POSIX states that only the lowermost 8 bits passed to exit shall be made available to a waiting parent process, literally as if it was "status & 0xFF".

          So, in practice, the exit code is a (still signed) integer of which only the lowest 8 bits are set.



          The minimum will thus be -128, and the maximum 127. Hang on, that's not true. It will be 0 to 255.



          But alas, of course it cannot be that simple. In practice, Linux (or rather bash) does it differently. The valid range of return codes is 0 to 255 (i.e. unsigned).



          To be on the safe side in terms of avoiding confusion, it's probably a good idea to just assume that return codes are unsigned, and cast anything you get back from wait to unsigned. That way it's consistent with what you see in a shell. Since the topmost bits (including the most significant one) are cleared out, that's not even "wrong" because although technically signed, the actual values are always unsigned (since the sign bit is never set).

          It also helps avoiding the common error of comparing an exit code to -1, which for some strange reason never seems to appear even when a program exits with -1 (well, guess why!).



          About your last point, returning from a function, if this function happens to be main, then see above. Otherwise, it depends on what the function's return type is, it could in principle be anything (including void).







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Apr 12 at 3:37









          Konstantin

          1254




          1254










          answered Jan 23 at 10:46









          Damon

          1,37978




          1,37978




















              up vote
              2
              down vote














              1. The exit code returned from a binary executable (for example: a C program).

              2. The exit code returned from a bash script (when calling exit).



              Exit codes from any process -- whether it's a binary executable, a shell script, or anything else -- range from 0 to 255. It's possible to pass a larger value to exit(), but only the lower 8 bits of the status are made available to other processes through wait().




              1. The exit code returned from a function (when calling return). I think this is between 0 and 255.



              A C function can be declared as returning almost any type. The limits of its return value are determined entirely by that type: for instance, -128 to 127 for a function returning signed char, or 0 to 4.2 billion for a function returning unsigned int, or any floating-point number up to and including inf for a function returning double. And that isn't counting the non-numeric types, like void * or a struct...






              share|improve this answer
























                up vote
                2
                down vote














                1. The exit code returned from a binary executable (for example: a C program).

                2. The exit code returned from a bash script (when calling exit).



                Exit codes from any process -- whether it's a binary executable, a shell script, or anything else -- range from 0 to 255. It's possible to pass a larger value to exit(), but only the lower 8 bits of the status are made available to other processes through wait().




                1. The exit code returned from a function (when calling return). I think this is between 0 and 255.



                A C function can be declared as returning almost any type. The limits of its return value are determined entirely by that type: for instance, -128 to 127 for a function returning signed char, or 0 to 4.2 billion for a function returning unsigned int, or any floating-point number up to and including inf for a function returning double. And that isn't counting the non-numeric types, like void * or a struct...






                share|improve this answer






















                  up vote
                  2
                  down vote










                  up vote
                  2
                  down vote










                  1. The exit code returned from a binary executable (for example: a C program).

                  2. The exit code returned from a bash script (when calling exit).



                  Exit codes from any process -- whether it's a binary executable, a shell script, or anything else -- range from 0 to 255. It's possible to pass a larger value to exit(), but only the lower 8 bits of the status are made available to other processes through wait().




                  1. The exit code returned from a function (when calling return). I think this is between 0 and 255.



                  A C function can be declared as returning almost any type. The limits of its return value are determined entirely by that type: for instance, -128 to 127 for a function returning signed char, or 0 to 4.2 billion for a function returning unsigned int, or any floating-point number up to and including inf for a function returning double. And that isn't counting the non-numeric types, like void * or a struct...






                  share|improve this answer













                  1. The exit code returned from a binary executable (for example: a C program).

                  2. The exit code returned from a bash script (when calling exit).



                  Exit codes from any process -- whether it's a binary executable, a shell script, or anything else -- range from 0 to 255. It's possible to pass a larger value to exit(), but only the lower 8 bits of the status are made available to other processes through wait().




                  1. The exit code returned from a function (when calling return). I think this is between 0 and 255.



                  A C function can be declared as returning almost any type. The limits of its return value are determined entirely by that type: for instance, -128 to 127 for a function returning signed char, or 0 to 4.2 billion for a function returning unsigned int, or any floating-point number up to and including inf for a function returning double. And that isn't counting the non-numeric types, like void * or a struct...







                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Jan 23 at 4:17









                  duskwuff

                  22416




                  22416






















                       

                      draft saved


                      draft discarded


























                       


                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function ()
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f418784%2fwhat-is-the-min-and-max-values-of-exit-codes-in-linux%23new-answer', 'question_page');

                      );

                      Post as a guest













































































                      Popular posts from this blog

                      How to check contact read email or not when send email to Individual?

                      Bahrain

                      Postfix configuration issue with fips on centos 7; mailgun relay