Score:1

Why does `/usr/bin/time` report the wrong exit status with format `%x` in case of SIGABRT?

bi flag

I'm using /usr/bin/time to report information about a set of benchmarks I'm running. The interesting data points are runtime, memory usage and the exit status. This works fine except when the application fails with an uncaught exception, in which case /usr/bin/time reports a 0 exit code instead of the actual 134.

Let me illustrate the problem with a toy example for the app:

#include <stdexcept>

int main(int argc, char** argv) {
    throw std::runtime_error("test"); // 1
    //return 134;                     // 2
}

and the following call: /usr/bin/time -f "%x" ./app ; echo $?.

Throwing the error (line 1 not commented) results in the following output:

terminate called after throwing an instance of 'std::runtime_error'
  what():  test
Command terminated by signal 6
0
134

whereas actually returning the exit status (line 2 not commented) works:

Command exited with non-zero status 134
134
134

/usr/bin/time --version reports an UNKNOWN version, but I see the same behavior on Ubuntu 20.04 and 22.04. I suspect it has something to do with the SIGABRT (signal 6), but I cannot find a fix or an explanation for the behavior.

How can I get /usr/bin/time to report the correct exit status in cases of uncaught exceptions?

muru avatar
us flag
Note that "134" might be a fiction made up by your shell. Bash, at least, when it sees that a child process was killed by a signal, sets the exit status to 128+<signal number>, but that's just Bash trying to be helpful.
Stefan avatar
bi flag
That's a good point. After reading a bit more into the topic of signals, I think I misunderstood how SIGABRT works. Do you think I makes sense to ask this question in Unix & Linux?
muru avatar
us flag
I think you find most of the information you need in https://unix.stackexchange.com/q/99112/70524. You can try something like `/usr/bin/time -f "%x" bash -c './app; exit $?'` instead to get the fake exit status reported by the shell, but your results for other statistics maybe slightly off due to the intervening shell.
Stefan avatar
bi flag
That really did help, both with understanding better how signals work and how to fix my issue. Do you want to post this as an answer?
Score:0
us flag

The exit status of 134 that you see here is the value reported by the shell, probably bash in this case, on behalf of the killed process to indicate that it was killed by a signal. The exact behaviour of this reporting varies between shells, so you'd see different values instead of 134 for the same situation with, say, ksh. The entire situation is explained thoroughly in the answers to this Unix & Linux post.

Worse yet, as this is a feature of the shell, other programs aren't expected to do the same. The time command instead prints a message notifying about the signal-induced termination (Command terminated by signal 6), but reports 0.

You can instead call the shell with time, and use it to report the exit status you want. This might influence other metrics that you might care about for benchmarking, but should work:

/usr/bin/time -f "%x" bash -c './app; exit $'

On Ubuntu, /bin/sh is dash, but it should have the same behaviour as bash in this respect according to the linked U&L post. As dash is considerably more lightweight than bash, you could use sh -c instead of bash -c here and have less of an impact on metrics.

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.