C - The correct range of return status / value

Recently, after reading a book on Linux programming, I received a message stating that:

The state argument assigned by _exit () determines the process termination status available to the parent of this process when it calls wait (). Although it is defined as int, only the basic 8 bits of status actually become available to the parent. And it is recommended to use it only 0 ~ 127, because for some reason 128 ~ 255 can get confused in the shell. In this regard, it -1will be 255in 2 additions.

The above is the exit status of the child process.

My question is:

  • Why does the parent process receive only 8 bits of the exit status of the child process?
  • What about the return value of normal functions? Does it make sense or not use only 0 ~ 127? Because I use it -1as a return value to sometimes indicate an error, should I fix it in the future.

Update - get by wait () / waitpid () status:

I read more chps in the book (TLPI) and found that the return status has more tricks and wait () / waitpid () worth mentioning, I had to read more chps before asking a question. Anyway, I will add one answer to describe it if this can help someone in the future.

+4
source share
2 answers

Why does the parent process receive only 8 bits of the exit status of the child process?

POSIX . POSIX , , Unix, , .

?

. , . -1 , , API C POSIX.

+4

@n.m. .

chps (TLPI) , wait()/waitpid(), , int .

:

  • 1 , wait()/waitpid(),
  • 2 LSB,

:

    event                   byte 1                  byte 0
    ============================================================
    * normal termination    exit status (0 ~ 255)   0
    * killed by signal      0                       termination signal (!=0)
    * stopped by signal     stop signal             0x7F
    * continued by signal               0xFFFF
    * 

:

header 'sys/wait.h',  defines a set of macros that help to dissect a wait status,

macros:
* WIFEXITED(status)
    return true if child process exit normally,
* 
* WIFSIGNALED(status)
    return true if child process killed by signal,
* WTERMSIG(status)
    return signal number that terminate the process,
* WCOREDUMP(status)
    returns ture if child process produced a core dump file,
    tip:
        this macro is not in SUSv3, might absent on some system,
        thus better check whether it exists first, via:
            #ifdef WCOREDUMP
                // ...
            #endif
* 
* WIFSTOPPED(status)
    return true if child process stopped by signal,
* WSTOPSIG(status)
    return signal number that stopp the process,
* 
* WIFCONTINUED(status)
    return true if child process resumed by signal SIGCONT,
    tip:
        this macro is part of SUSv3, but some old linux or some unix might didn't impl it,
        thus better check whether it exists first, via:
            #ifdef WIFCONTINUED
                // ...
            #endif
* 

wait_status_test.c

// dissect status returned by wait()/waitpid()
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/wait.h>

#define SLEEP_SEC 10 // sleep seconds of child process,

int wait_status_test() {
    pid_t cpid;

    // create child process,
    switch(cpid=fork()) {
        case -1: // failed
            printf("error while fork()\n");
            exit(errno);
        case 0: // success, child process goes here
            sleep(SLEEP_SEC);
            printf("child [%d], going to exit\n",(int)getpid());
            _exit(EXIT_SUCCESS);
            break;
        default: // success, parent process goes here
            printf("parent [%d], child created [%d]\n", (int)getpid(), (int)cpid);
            break;
    }

    // wait child to terminate
    int status;
    int wait_flag = WUNTRACED | WCONTINUED;
    while(1) {
        if((cpid = waitpid(-1, &status, wait_flag)) == -1) {
            if(errno == ECHILD) {
                printf("no more child\n");
                exit(EXIT_SUCCESS);
            } else {
                printf("error while wait()\n");
                exit(-1);
            }
        }
        // disset status
        printf("parent [%d], child [%d] ", (int)getpid(), (int)cpid);
        if(WIFEXITED(status)) { // exit normal
            printf("exit normally with [%d]\n", status);
        } else if(WIFSIGNALED(status)) { // killed by signal
            char *dumpinfo = "unknow";
            #ifdef WCOREDUMP
                dumpinfo = WCOREDUMP(status)?"true":"false";
            #endif
            printf("killed by signal [%d], has dump [%s]\n", WTERMSIG(status), dumpinfo);
        } else if(WIFSTOPPED(status)) { // stopped by signal
            printf("stopped by signal [%d]\n", WSTOPSIG(status));
        #ifdef WIFCONTINUED
        } else if(WIFCONTINUED(status)) { // continued by signal
            printf("continued by signal SIGCONT\n", WSTOPSIG(status));
        #endif
        } else { // this should never happen
            printf("unknow event\n");
        }
    }

    return 0;
}

int main(int argc, char *argv[]) {
    wait_status_test();
    return 0;
}

Compile:

gcc -Wall wait_status_test.c

Execute:

  • ./a.out , , fork(),
  • ./a.out, kill -9 <child_process_id>, ,
  • ./a.out, kill -STOP <child_process_id> , kill -CONT <child_process_id>, ,
+1

All Articles