TL;DR
All job control / crash messages are hidden when they occur within a function. I go into more detail below, but @Barmar has pointed out that this issue can be reproduced by running a crashing binary inside of a function, e.g:
crun() {
/tmp/faulty $1 $2 $3
}
I've defined a function in my .zshrc
to compile & run source code with the function below:
crun() {
local file=$1
shift
local exepath="$(mktemp)"
if [[ $file =~ "\.c$" ]]; then
gcc -g -Wall $file -o $exepath || return $?
else
echo "no filetype detected"
return 126
fi
$exepath "$@"
}
Which can be called in this fashion:
% crun source.cc arg_1 arg_2
This works for normal programs, but has the problem that the shell's job control messages, such as those generated from a segfault, do not appear.
As an example:
% echo 'int main=0;' >> /tmp/faulty.c # a crashing c program
% crun faulty.c
% # no output generated
Whereas the equivalent interactive commands would generate this:
% g++ faulty.c -o /tmp/faulty && /tmp/faulty
[1] 2894 segmentation fault (core dumped) # 🢀 zsh's job control output for SIGSEGV
Is there any way to display these messages for a crashing executable whose path is dynamically calculated? Ideally without writing your own trap/signal handlers + exec
, using sh -c "$exepath $@"
, or writing a totally new system(3)
wrapper entirely)
You can get zsh
to print the segmentation fault message from the job if you start it as a background job and then immediately bring it to the foreground.
"$exepath" "$@" &
fg
This will cause zsh
to print out messages for signals on the job started for $exepath
.
The downside is that you will get a little bit more than you bargained for:
% crun faulty.c
faulty.c:1:5: warning: ‘main’ is usually a function [-Wmain]
int main=0;
^~~~
[2] 2080
[2] - running "$exepath" "$@"
zsh: segmentation fault (core dumped) "$exepath" "$@"
But as shown, you will get the segfault messages printed in the terminal.
Because the messages are printed by the interactive shell, not the failing process, the job messages won't get redirected should you try to redirect stdout
or stderr
.
So on the one hand, should you try to take useful output out of your running process and redirect it somewhere else, you don't need to worry about the job messages getting in the way. But this also means you won't get the segfault message should you try to redirect it by redirecting stderr
.
Here's a demonstration of this effect, with line breaks added in-between commands for clarity:
% crun good.c > test
[2] 2071
[2] - running "$exepath" "$@"
% cat test
Hello, world!
% crun faulty.c 2>test
[2] 2092
[2] - running "$exepath" "$@"
zsh: segmentation fault (core dumped) "$exepath" "$@"
% cat test
faulty.c:1:5: warning: ‘main’ is usually a function [-Wmain]
int main=0;
^~~~
For more information, see zsh
's documentation on jobs and signals. You can also poke around the C file where the magic happens.
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