Question

I have an ARM-based device running Embedded Linux and I have observed that when I use the C library's system() call, the return code is incorrect. Here is a test program that demonstrates the behavior:

#include <stdlib.h>
#include <stdio.h>

int main(void)
{
    int ret = system("exit 42");
    printf("Should return 42 for system() call: %d\n", ret);
    printf("Returning 43 to shell..\n");
    exit(43);
};

And here is the program output on the device:

# returnCodeTest                 
Should return 42 for system() call: 10752
Returning 43 to shell..

The value "10752" is returned by system() instead of "42". 10752 is 42 when left-shifted by 8:

Python 2.7.3 (default, Feb 27 2014, 20:00:17) 
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> 42<<8
10752

So is suspect one of the following is going on somewhere:

  1. The byte order is getting swapped
  2. The value is getting shifted by 8 bits
  3. Incompatible struct definitions are being used

When I run strace I see the following:

# strace /usr/bin/returnCodeTest 
...
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x4001e308) = 977
wait4(977, [{WIFEXITED(s) && WEXITSTATUS(s) == 42}], 0, NULL) = 977
rt_sigaction(SIGINT, {SIG_DFL, [], 0x4000000 /* SA_??? */}, NULL, 8) = 0
rt_sigaction(SIGQUIT, {SIG_DFL, [], 0x4000000 /* SA_??? */}, NULL, 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=977, si_status=42, si_utime=0, si_stime=0} ---
fstat64(1, {st_mode=S_IFCHR|0622, st_rdev=makedev(136, 0), ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x4001f000
write(1, "Should return 42 for system() ca"..., 42Should return 42 for system() call: 10752
) = 42
write(1, "Returning 43 to shell..\n", 24Returning 43 to shell..
) = 24
exit_group(43)                          = ?
+++ exited with 43 +++

wait4() returns with the correct status (si_status=42), but when it gets printed to standard output the value is shifted by 8 bits, and it looks like it is happening in a library. Interestingly the write returns a value of 42. I wonder if this is a hint as to what is going on...

Unfortunately I cannot get ltrace to compile and run on the device. Has anyone seen this type of behavior before or have any ideas (possibly architecture-specific) on where to look?

Was it helpful?

Solution

$man 3 system

Return Value

The value returned is -1 on error (e.g., fork(2) failed), and the return status of the command otherwise. This latter return status is in the format specified in wait(2). Thus, the exit code of the command will be WEXITSTATUS(status).

$man 2 wait

WEXITSTATUS(status) returns the exit status of the child. This consists of the least significant 8 bits of the status argument that the child specified in a call to exit(3) or _exit(2) or as the argument for a return statement in main(). This macro should only be employed if WIFEXITED returned true.

OTHER TIPS

I think exit codes are different from return values and is specific to OS.

Linux does the following when you call "exit" with a code.

(error_code&0xff)<<8

SYSCALL_DEFINE1(exit, int, error_code)
{
        do_exit((error_code&0xff)<<8);
}

Take look at the below link (exit status codes in Linux).

Are there any standard exit status codes in Linux?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top