Re: [PATCH RFC] kbuild: enable pipefail for commands where possible

From: Thomas Weißschuh

Date: Thu Oct 15 2026 - 06:27:04 EST


On Wed, Oct 14, 2026 at 02:40:43PM -0700, Nathan Chancellor wrote:
> On Wed, Oct 14, 2026 at 10:30:30AM +0200, Thomas Weißschuh wrote:
> > The exit status of a shell pipeline by default only depends on the exit
> > status of its last command. If an earlier command fails this is silently
> > ignored. In this case the build continues operating on intermediate
> > state, potentially leading to confusing follow-up failures.
> >
> > The 'pipefail' option can be used to exit the pipeline with an error as
> > soon as a single of its command fails which 'set -e' will elevate to
> > error exit of the whole command.
> >
> > 'pipefail' has been only standardized in POSIX 2024, but it is supported
> > by many shells anyways, including bash and dash. To avoid issues with
> > shells not implementing it, ignore failures silently.
> >
> > Reported-by: kernel test robot <lkp@xxxxxxxxx>
> > Link: https://lore.kernel.org/oe-kbuild-all/202610131613.BpOi6VPp-lkp@xxxxxxxxx/
> > Signed-off-by: Thomas Weißschuh <thomas.weissschuh@xxxxxxxxxxxxx>
>
> This is probably the right thing to do but it makes me nervous. pipefail
> is very easy to hold wrong mainly because of SIGPIPE:
>
> $ cat test.sh
> set -o pipefail
>
> yes | head -n +50
>
> $ bash test.sh
> ...
>
> $ echo $?
> 141
>
> and debugging that is unlikely to be obvious (but maybe it will because
> the error would be 141).

It actually breaks modversions quite badly. And it is not obvious to debug
as that uses the pipe in an `if` statement which swallows the 141 silently.

Not sure what to do here.

Maybe we just provide `try-pipefail` so users can opt-in where it makes sense.


Also

try-pipefail = set -o pipefail || true 2>/dev/null

should have been

try-pipefail = set -o pipefail 2>/dev/null || true

> > ---
> > scripts/Kbuild.include | 5 ++++-
> > 1 file changed, 4 insertions(+), 1 deletion(-)
> >
> > diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include
> > index 8c311b997e24..1975d2739cdb 100644
> > --- a/scripts/Kbuild.include
> > +++ b/scripts/Kbuild.include
> > @@ -149,8 +149,11 @@ delete-on-interrupt = \
> > $(foreach sig, HUP INT QUIT TERM PIPE, \
> > trap 'rm -f $@; trap - $(sig); kill -s $(sig) $$$$' $(sig);))
> >
> > +# try to enable pipefail
> > +try-pipefail = set -o pipefail || true 2>/dev/null
> > +
> > # print and execute commands
> > -cmd = @$(if $(cmd_$(1)),set -e; $($(quiet)log_print) $(delete-on-interrupt) $(cmd_$(1)),:)
> > +cmd = @$(if $(cmd_$(1)),$(try-pipefail); set -e; $($(quiet)log_print) $(delete-on-interrupt) $(cmd_$(1)),:)
> >
> > ###
> > # if_changed - execute command if any prerequisite is newer than