Discussion:
[ast-users] ksh-93u+ pipefail option does not trigger errexit or ERR trap after pipe errors
Milton Woods
2015-11-03 23:22:47 UTC
Permalink
Hi ksh maintainers,

I have noticed a change in handling of the pipefail option in ksh. The
change occurred somewhere between ksh-93t+ and ksh-93u+.

When the pipefail option is set, command pipelines return an error
(non-zero) status if any process in a pipeline returns an error status.
In ksh-93t+, an error status from any pipeline stage triggers an ERR
trap or errexit. In ksh-93u+, a pipeline returns the expected error
status if any command returns an error, but execution continues as
though the error did not occur (unless the error comes from the last
pipeline stage). For example:

#!/bin/ksh
set -o pipefail
set -e errexit
trap 'echo ERR' ERR
false | true
echo "Continued past error $?"

Without the pipefail option, "false | true" would return 0, but with the
pipefail option, it returns 1. In ksh-93t+, the above commands display
"ERR" and exit the shell. But in ksh-93u+, the message "Continued after
error 1" is displayed without exiting the shell, indicating that the
error status from the pipeline is not triggering either the ERR trap or
errexit option.

Is this change in behaviour a deliberate feature, or does it indicate a
bug?

Regards,
Milton.
Richard Hamilton
2015-11-04 05:39:51 UTC
Permalink
AFAICT from the man page, that should be either "set -e" or "set -o
errexit"; however, it doesn't make any difference as to the result.

If I read the man page fairly literal-mindedly, I would think your
description of the old behavior is a better fit, and and the new behavior
is a bug. But the language isn't quite precise enough for me to say that
based simply on the man page; it comes down to knowing what was intended
when the change was made (or
=====================================================
If sig is ERR then action will be executed whenever a command has a
non-zero exit status.
=====================================================
-e Unless contained in a || or && command, or the command
following an if while or until command or in the pipe-
line following !, if a command has a non-zero exit sta-
tus, execute the ERR trap, if set, and exit. This mode
is disabled while reading profiles.
=====================================================
The exit status of a pipeline is the exit status of the last command
unless the pipefail option is enabled.
=====================================================
pipefail
A pipeline will not complete until all compo-
nents of the pipeline have completed, and the
return value will be the value of the last non-
zero command to fail or zero if no command has
failed.
​=====================================================

In particular, the language for the ERR trap and for -e seems to differ
beyond just the exceptions for -e (where a test or evaluation is being
performed or "!" is used). Nevertheless, it seems reasonable that
"pipefail" affects either both of ERR and -e, or neither.

The POSIX shell spec seems of no help; what it describes is effectively a
subset of modern Korn Shell. It says:

The KornShell uses an *ERR* trap that is triggered whenever *set*
<http://pubs.opengroup.org/onlinepubs/009695399/utilities/set.html> *-e* would
cause an exit. This is allowable as an extension, but was not mandated, as
other shells have not used it.
In other words, the POSIX spec does not appear to require the existence of
an ERR trap (although it does that of set -e, and describes ERR for Korn
Shell in terms of set -e). I also do not see the "pipefail" option in the
POSIX shell spec.

Here's an argument in favor of it being a bug: bash, or at least the
version of bash on my system (see below), behaves like the old behavior you
describe. All other things being equal, where the same features exist
between ksh93 and bash, one might hope for the same behavior.

bash-3.2$ bash --version
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin15)
Copyright (C) 2007 Free Software Foundation, Inc.
Milton Woods
2015-11-05 08:29:55 UTC
Permalink
Hi Richard,

Thanks for pointing out the typo in my test script. It should be “set -e” or “set -o errexit” (which I think are equivalent) instead of “set -e errexit”.

I should have mentioned that the change in behaviour is not limited to the case when _both_ the errexit option and ERR trap are enabled. It also applies when either option is enabled individually - neither of them is triggered by an error in a pipeline (in ksh-93u+).

As the change in behaviour does not seem to be documented, I suspect that a bug was introduced in ksh somewhere between 93t+ and 93u+.

Is there a formal way to report a bug in Korn shell, other than sending email to this list?

Regards,
Milton.

Loading...