On 2020-12-24 Sebastian Andrzej Siewior wrote: > The `cmp' command will return early if a difference is found while the > shell script is still invoking the decompressor which writes into the > closed FD. This results in SIGPIPE / exit code 141. > By ignoring SIGPIPE the real return code from `cmp' is observed which > is `1' and xzdiff exits with `1'. Without ignoring SIGPIPE the > exitcode 141 is observed and xzdiff returns with `2'.
Thanks! Seems that the exit statuses of xzcmp and xzdiff have been broken maybe as long as they have been included in XZ Utils. The problem seems to be more hairy than it appears at first. Adding just one "trap" isn't a complete fix. xzdiff supports formats other than .xz too. gzip and lzop change their behavior if SIGPIPE is ignored. They print an error message about broken pipe and exit with status 1. That is, then it's not possible to distinguish between actual SIGPIPE and corrupt input. It's tempting to ignore exit statuses >= 128 at the end of the script where it current checks for "$xz_status" -eq 0 but that doesn't work because in the middle of the script there is also this: case $xz_status in *[1-9]*) xz_status=1;; *) xz_status=0;; esac There xz_status contains two numbers and the "case" finds out if they are both zero. Perhaps this "case" should be replaced with something more sophisticated that checks both numbers separately and ignores values >= 128. Obviously it's not problem free to ignore >= 128 since that could hide bad signals like SIGSEGV. At this point I feel it's not too bad but perhaps someone else has better ideas. As a bonus, the script already uses "trap" to delete temporary files. I think that code path is never used if the shell is fancy enough to do complex redirections. However, it traps also SIGPIPE and I think it can in such situations run rm -rf twice on the same path name. That feels suspicious but perhaps it's not too bad, especially since the code likely is never used on most systems. -- Lasse Collin | IRC: Larhzu @ IRCnet & Freenode