exit()

Discussion in 'C Programming' started by BartC, Feb 14, 2013.

  1. BartC

    BartC Guest

    Can I use the return value provided to exit() for my own purposes?

    (This is so that I can pick up the exit-value when I invoke the program from
    another. BTW what's the best way of invoking a program under Linux so that
    this value can be retrieved?)
     
    BartC, Feb 14, 2013
    #1
    1. Advertisements

  2. BartC

    John Gordon Guest

    Yes. However program exit codes are fairly limited in range; I believe
    you can only use values from 0 to 255.
    From a shell, the exit status of the previous command is typically
    available from the $? variable.

    If you're invoking a program from another program, the invoking function
    (typically something like system("command")) will usually return the exit
    status. Although, in this case, the returned value may be a combination
    of the program's exit command and the shell that was spawned to run it;
    you may have to separate out the two values.
     
    John Gordon, Feb 14, 2013
    #2
    1. Advertisements

  3. That's true for Unix/Linux/POSIX systems. It may or may not be true for
    other systems.

    The C standard says that exit() takes an int argument. It causes the
    program to terminate and return a implementation-defined status to
    the environment (0 or EXIT_SUCCESS should return a status denoting
    success, and EXIT_FAILURE should return a status denoting failure).
    That's for the Bourne shell and shells derived from it. csh and tcsh
    use $status.
    The documentation for the system() function for your environment will
    tell you how to interpret the result returned by system(). On Unix-like
    systems, if a program invoked by system() calls exit(N), system() will
    return N<<8. system() returns other values if the program terminated
    due to a signal.
     
    Keith Thompson, Feb 14, 2013
    #3
  4. Under Linux (and POSIX), the exit value has no predefined meaning (but a
    limited range, and conventions). If you control the whole chain, you're
    probably invoking from a parent process with fork/exec*. Then the parent
    can use wait() to retrieve the exit code (after having checked whether
    the child terminated by calling exit()). If you use higher-level
    interfaces to launch the program (e.g., system()), you may loose some
    accuracy

    -- Alain.
     
    Alain Ketterlin, Feb 14, 2013
    #4
  5. exit(0) and exit(EXIT_SUCCESS) are well defined, both by C and by
    POSIX, as an indication of success. exit(EXIT_FAILURE) denotes
    failure. (EXIT_FAILURE is typically 1 on POSIX systems, but the
    POSIX standard doesn't require that.)
    The value returned by system() is well defined for POSIX; it's the same
    as the result returned by waitpid(). If you evaluate

    system("some_command");

    and some_command calls exit(42), you can reliably get the value 42 from
    the result returned by system().

    Some specific commands define meanings for exit statuses other than 0 or
    1. For example, the grep command exits with a status of 0 on success, 1
    on failure, and 2 on error. The curl command defines 88 different error
    codes, but that's an extreme case.
     
    Keith Thompson, Feb 15, 2013
    #5
  6. BartC

    Nobody Guest

    Note that if execve() failed to execute the shell, the result is the same
    as a program which does exit(127), so you probably shouldn't use 127 as
    one of your program's exit codes.

    Also, note that you need to use the macros from <sys/wait.h> to extract
    the actual exit status (and to determine if there is an exit status to
    extract, as opposed to e.g. a signal). The value returned from waitpid(),
    system() etc combines various pieces of information into a single integer.
     
    Nobody, Feb 15, 2013
    #6
  7. BartC

    Noob Guest

    As others have pointed out, the answer is platform-dependent.
    Try comp.unix.programmer or comp.os.linux.development.apps
     
    Noob, Feb 15, 2013
    #7
  8. See, a value of 42 has no predefined meaning.
    This is wrong if system() returns 127.

    [...]
    It seems obvious to me that BartC needs something like that.

    -- Alain.
     
    Alain Ketterlin, Feb 15, 2013
    #8
  9. BartC

    James Kuyper Guest

    But a value of 0 does. Therefore, saying that "the exit value has no
    predefined meaning", without restricting that statement to a particular
    range of exit values, was incorrect.
     
    James Kuyper, Feb 15, 2013
    #9
  10. Certainly -- but 0 does. Your statement that "the exit value has no
    predefined meaning" is mostly correct, but incomplete.

    [...]
     
    Keith Thompson, Feb 15, 2013
    #10
  11. BartC

    Jorgen Grahn Guest

    IME grep is an extreme case too. The vast majority of Unix tools
    return 0 for success, and 1 for errors.
    Why is that obvious? He didn't say anything about his actual problem,
    and again: designs which rely on many different exit codes are rare.

    Perhaps his needs are best served by printing something to stdout and
    returning 0/1.

    /Jorgen
     
    Jorgen Grahn, Feb 16, 2013
    #11
  12. BartC

    BartC Guest

    Sometimes I need to return two values (usually 1 for success, 0 for failure;
    the opposite of above); sometimes three or four (an exit code from an editor
    for example that may contain a request to compile the result). A range of
    0..255, or even a limited subset, would be more than adequate. And better
    than having to communicate via files, although this is what I have to do
    with programs such as gcc for example, to figure out if something compiled
    without errors.

    (And on Windows there is a special function to pick up this exit code. While
    a system() function exists (and is considerably simpler to use), it's return
    value seems unrelated to the exit code of any program it attempts to run.)
     
    BartC, Feb 16, 2013
    #12
  13. If you need two return values denoting success and failure, you should
    use 0 and EXIT_FAILURE, respectively, or EXIT_SUCCESS and EXIT_FAILURE.
    If you use `exit(0)` for failure and `exit(1)` for success, your program
    won't interoperate with other programs on the same system. On Unix-like
    systems, for example, the usual logic of

    some_program || echo "It failed" 1>&2

    would not work.

    And gcc on Unix-like systems follows the usual convention of
    exiting with a status of 0 for success, non-0 for failure.
    (Makefiles routinely take advantage of that.)
    Really? I just tried an experiment on Windows 7 with
    MS Visual C++ 2010 Express (compiling C code, not C++).
    It seems to indicate that the result returned by system()
    is exactly the same as the value passed to exit() by the
    called program -- which agrees with Microsoft's documentation:
    http://msdn.microsoft.com/en-us/library/277bwbdz(v=vs.110).aspx

    Though there is a note that says "This API cannot be used in
    applications that execute in the Windows Runtime".
     
    Keith Thompson, Feb 16, 2013
    #13
  14. BartC

    BartC Guest

    Maybe I can do that, and reverse the two after the value has been retrieved.
    That's if I can use the (to me) counter-intuitive values in the first place
    (I always use an actual 1 or 0).
    So it does. I must have read those docs too carefully (they mention nothing
    of exit codes), together with some presumably flawed tests. Even gcc is
    giving a 0 or 1 (but again, to me, back-to-front) result.

    Perhaps I can make more use of system() then, since that is more portable.
     
    BartC, Feb 16, 2013
    #14
  15. My advice: get used to the fact that Unix commands (and, I think,
    many Windows commands as well) return a status of 0 for success,
    non-0 for failure.

    The reason is that there's typically only one way for a program to
    succeed, and many ways for it to fail. The status result can (in an
    ad hoc way) provide more information about the nature of the failure.

    There's no real need to convert the 0=success, non-0=failure value to
    something you find more intuitive. Just think of it as a status code,
    not a Boolean. To test whether a program succeeded or failed:

    if (system("...") == 0) {
    /* success */
    }
    else {
    /* failure */
    }
    "More portable" meaning, in this case, that it works reasonably on
    Unix-like and Windows-like systems (though the Unix return value is more
    complicated). If that's portable enough for you, great. But IMHO it's
    important to be aware that the C standard doesn't say much about the
    meaning of the value returned by system(), or about its relationship, if
    any, to the value passed to exit(). The behavior could be quite
    different on other systems.
     
    Keith Thompson, Feb 16, 2013
    #15
  16. I first knew return codes from OS/360, where they are usually mutliples
    of four, but otherwise 0 is usually success, 4 a little worse
    (warning), 8 is about what is usually called error (returned by
    compilers that could keep compiling, at least for syntax checking),
    then 12 for fatal errors (the compiler gave up), and 16 even worse
    (such as the inability to open SYSPRINT, what some might call stdout).
    But this is comp.lang.c where booleans are int.

    It does confuse things like the tests in csh, where success is 0,
    and apply to the && and || operators.

    (Which are supposed to work like C operators.)

    -- glen
     
    glen herrmannsfeldt, Feb 16, 2013
    #16
  17. BartC

    James Kuyper Guest

    On 02/16/2013 05:46 PM, glen herrmannsfeldt wrote:
    ....
    _Bool b = 3;

    The resulting value of 'b' does not quite fit your description.
     
    James Kuyper, Feb 17, 2013
    #17
  18. Would it still be counter-intuitive if you regard the result of an
    application not as a boolean, but as a status code (with 0 == "success",
    EXIT_FAILURE == "generic failure", other values more specific failure
    codes)?
    Or do you then also use 1 for success and several values of 0 to indicate
    the various failures?

    Bart v Ingen Schenau
     
    Bart van Ingen Schenau, Feb 17, 2013
    #18
  19. The core problem underlying all of this - is the fact that the shell treats
    a return value of 0 as "TRUE" and anything else (i.e., non-zero) as FALSE.
    Which is the exact opposite of what C (and most other programming languages)
    do. Hence the confusion. Digging further, what underlies that is a basic
    intuitive feeling that "TRUE" should be "good" and FALSE "bad", which, I
    think, corresponds with most people's basic feelings about the Universe.

    Interestingly enough, the first platform I ever used that used the concept
    of TRUE/FALSE to indicate error/success, did so in that order - namely,
    TRUE == error and FALSE == success. Counterintuitive this was, but it got
    the job done nicely.

    Finally, note that the Windows API mostly follows the model that 0 == failure,
    1 (although this is usually documented as "non-zero") == success, because
    this is what most people (unless they've come from a Unix background) expect
    and are comfortable with, even though it is technically less efficient.

    Since it is clear that "BartC" comes from a Windows background, it seems
    reasonable to assume that that explains why he is more comfortable with the
    Windows model.

    --
    But the Bush apologists hope that you won't remember all that. And they
    also have a theory, which I've been hearing more and more - namely,
    that President Obama, though not yet in office or even elected, caused the
    2008 slump. You see, people were worried in advance about his future
    policies, and that's what caused the economy to tank. Seriously.

    (Paul Krugman - Addicted to Bush)
     
    Kenny McCormack, Feb 17, 2013
    #19
  20. It may be a bit off the wall, but this always makes me think of the
    opening of Anna Karenina:

    "Happy families are all alike; every unhappy family is unhappy in its
    own way."

    Information is only needed to record the result of an unhappy program.
     
    Ben Bacarisse, Feb 17, 2013
    #20
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.