I was writing a test to see if I could reliably determine the integer value of an exit code
with wait
.
1. Why is the exit code multiplied by 256?
2. Is exit()
, wait()
, the OS, or something else doing the multiplication?
The code to reproduce the issue.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
// implementation is correct but irrelevant to the question
int compareInt(const void* a, const void* b);
int main(void) {
pid_t pids[6];
int i;
for (i = 0; i < 6; i++) {
pid_t pid = fork();
pids[i] = pid;
if (pid == 0) {
exit(i);
}
}
int codes[6];
do {
i--;
wait(&codes[i]);
} while (i > 0);
const size_t num_elem = 6;
qsort(codes, num_elem, sizeof(int), compareInt);
for (i = 0; i < 5; i++) {
printf("%d, ", codes[i]);
}
printf("%d\n", codes[5]);
return 0;
}
Outputs: 0, 256, 512, 768, 1024, 1280
As it turns out I should be using wifexited(), wifstopped(), wifsignaled(), wexitstatus(), wtermsig(), or wstopsig()
to determine the exit status.
In addition the same behaviour is reproducible in PHP (where I first encountered it)
$pids = [];
foreach (range(0, 5) as $i) {
$pids[] = $pid = pcntl_fork();
if ($pid === 0) {
exit($i);
}
}
$exit_codes = [];
do {
pcntl_wait($exit_codes[]);
array_pop($pids);
} while (count($pids) > 0);
sort($exit_codes);
echo implode(', ', $exit_codes) . "\n";
Outputs: 0, 256, 512, 768, 1024, 1280
If it makes a difference I am running Ubuntu 14.04 and man wait
says I have WAIT(2)
The reasons you're seeing those results is because the returned value from wait()
is encoded and contains information such as how and why the process was stopped as well as the actual exit status; this is why convenience macros are supplied to inspect certain parts of the return value.
A definition of WEXITSTATUS(status)
can be found in sys/wait.h
and may look like this:
#define WEXITSTATUS(status) (((status) & 0xff00) >> 8)
Or this:
#define WEXITSTATUS(status) (((status) >> 8) & 0x000000ff)
So you're seeing the multiplication because:
exit(1) -> 0x0100 (256)
exit(2) -> 0x0200 (512)
In PHP you would use pcntl_wexitstatus()
to accomplish the same thing; if the process was killed due to a signal there would be no exit status and you would need to use pcntl_wtermsig()
to determine the signal that was used to kill it.
The return value of wait()
encodes several pieces of information. There are macros defined to pick apart the results and get just the nit you need. e.g. WEXITSTATUS(result_of_wait)
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With