#1147088 git invokes hook scripts with SIGPIPE ignored

Package:
git
Source:
git
Description:
fast, scalable, distributed revision control system
Submitter:
Ian Jackson
Date:
2026-09-07 11:59:03 UTC
Severity:
normal
#1147088#5
Date:
2026-09-07 11:39:06 UTC
From:
To:
Hi again.  My hunch about #1146518 turned out to be correct.  I'm
filing this (duplicate) bug with formal Steps etc. because that one
starts with an indecypherable test log.

SUMMARY

git has started running at least some of the hook scripts (.git/hooks)
with SIGPIPE ignored.

I think this change is probably unintentional.  It is not uncommon for
programs to start ignoring SIGIPE internally and then forget to
restore it when running subprocesses.

STEPS

In an initialised git repository, which does not have a local branch t,

$ ed .git/hooks/pre-receive
.git/hooks/pre-receive: No such file or directory
$a
#!/bin/sh
set -e
perl -MData::Dumper -e 'print Dumper($SIG{PIPE})' >&2
.
w
71
q
$ chmod +x .git/hooks/pre-receive
$ git push . main:t

EXPECTED OUTPUT

Total 0 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
remote: $VAR1 = undef;
To .
 * [new branch]      main -> t
$ x

ACTUAL OUTPUT

Total 0 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
remote: $VAR1 = 'IGNORE';
To .
 * [new branch]      main -> t
$

DISCUSSION

Nonconsenting programs should not (in general) be invoked with
non-default signal dispositions.

In practice, setting SIGPIPE to SIG_IGN can cause unusual and
stochastic failures, especially when programs have careful error
handling.

Consider the pipeline
   seq | head

This pipeline should be considered successful even if seq dies with
SIGPIPE.  But it should not be considered successful if seq fails for
some other reason.  (Perhaps it's been replaced with a buggy Rust
rewrite.)

But if seq is run with SIGPIPE ignored, it will see EPIPE on its
stdout and exit nonzero.

In practice, I have seen these problems with dgit(1) and dpkg(1).
dgit(1) has a defensive check at the start, to catch this kind of
thing.  Such failures can depend on precise file sizes, buffering, and
execution order.

In theory, git could declare it part of the hook script API that the
hook is run with SIGPIPE ignored.  But that would be an incompatible
change compared to previous versions of git, and it seems like it
would be unwise given that the expectation is for hooks to be shell
scripts that invoke arbitrary commands.  Such a change would have to
be accompanied by an explicit reset of SIGPIPE at the top of each
example hook script.  (And manipulating signals like that in shell is
awkward.)

Anyway it seems likely that the external behavioural change is the
result of accidental leakage of internal signal disposition.  If I'm
right then the fix will involve searching git for all places that
fork/exec (or spawn) and ensuring that they (or the routines they use)
restore SIGPIPE to SIG_DFL.  Probably, more than just hook scripts are
affected.  Eg, git must also invoke ssh with SIGPIPE set to SIG_DFL.

Thanks for your attention.

Ian.