Why does spawned program exit code change when debugging?
assert, c, c++, exit-code, linux
Solution
The <sys/wait.h> header file contains macros for analyzing return codes.
To check the reason for exit, you can do something like this:
#include <stdio.h>
#include <sys/wait.h>
...
void run(const char *command)
{
int retcode = system(command);
if (WIFEXITED(retcode))
{
int status = WEXITSTATUS(retcode);
if (status)
{
printf("Exited normally with FAILURE status of %d!\n", status);
}
else
{
printf("Exited normally with SUCCESS(0) status!\n");
}
}
else if (WIFSIGNALED(retcode))
{
int signal = WTERMSIG(retcode);
printf("Abnormal termination - program crashed or was aborted with signal %d\n", signal);
}
}
See "man waitpid" for a description of these macros.
Problem
I have a C++ program that I'm using to test that another program doesn't crash. The parent code(we'll call it 'parentProg') looks something like this: ``` int run(const char * command) { ... int retCode = system(command); printf("Code is %d\n",retCode); if(retCode == 134) //128 + SIGABORT { // Record error conditions ... } } ``` The command variable contains the program being tested(we'll call it 'childProg'). With a previous Linux distribution, this code worked as expected. If a.out crashed or hit an assertion, it would return 134 and the error handling code would run. However after I upgraded to a newer Linux distribution this is no longer the case. Instead I see a return code of 6 when run as a spawned program, using GDB, or nemiver. Strangely, it reverts back to 134 if I run the child program alone, or using DDD. For the following tests I've modified childProg to be only the following code: ``` #include <assert.h> int main(int argc, char * argv[]) { assert(0); return 0; } ``` childProg by itself ``` [user@localhost multi]$ ./childProg childProg: temp.cpp:5: int main(int, char **): Assertion `0' failed. Abort [user@localhost multi]$ echo $? 134 ``` parentProg which spawns childProg ``` [user@localhost multi]$ ./parentProg 1 o Running 1 times childProg: temp.cpp:5: int main(int, char **): Assertion `0' failed. Code is 6 Done 0 [user@localhost multi]$ ``` With GDB ``` (gdb) run Starting program: parentProg 1 o Running 1 times Detaching after fork from child process 3311. childProg: temp.cpp:5: int main(int, char **): Assertion `0' failed. Code is 6 Done 0 [Inferior 1 (process 3295) exited normally] (gdb) ``` With DDD ``` (gdb) run 1 o Starting program: parentProg 1 o Running 1 times Detaching after fork from child process 3336. childProg: temp.cpp:5: int main(int, char **): Assertion `0' failed. Code is 134 Done 0 [Inferior 1 (process 3319) exited normally] (gdb) ``` This works as expected ``` [me@localhost multi]$ /bin/sh -c ./childProg childProg: temp.cpp:5: int main(int, char **): Assertion `0' failed. Abort [me@localhost multi]$ echo $? 134 ``` What could possibly be going on here? Is there a better way to check for crashing/segfaults/assertions other than checking the exit code?