Skip to content

Commit 131f031

Browse files
committed
Merge branch 'pr/use-default-sigpipe-setting'
We used to get confused when a process called us with SIGPIPE ignored; we do want to die with SIGPIPE when the output is not read by default, and do ignore the signal when appropriate. * pr/use-default-sigpipe-setting: mingw.h: add dummy functions for sigset_t operations unblock and unignore SIGPIPE
2 parents 0bf7dd6 + 4e6d207 commit 131f031

File tree

3 files changed

+50
-1
lines changed

3 files changed

+50
-1
lines changed

compat/mingw.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,6 @@ struct sigaction {
6969
sig_handler_t sa_handler;
7070
unsigned sa_flags;
7171
};
72-
#define sigemptyset(x) (void)0
7372
#define SA_RESTART 0
7473

7574
struct itimerval {
@@ -116,6 +115,12 @@ static inline int fcntl(int fd, int cmd, ...)
116115
}
117116
/* bash cannot reliably detect negative return codes as failure */
118117
#define exit(code) exit((code) & 0xff)
118+
#define sigemptyset(x) (void)0
119+
static inline int sigaddset(sigset_t *set, int signum)
120+
{ return 0; }
121+
#define SIG_UNBLOCK 0
122+
static inline int sigprocmask(int how, const sigset_t *set, sigset_t *oldset)
123+
{ return 0; }
119124

120125
/*
121126
* simple adaptors

git.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -592,6 +592,26 @@ static int run_argv(int *argcp, const char ***argv)
592592
return done_alias;
593593
}
594594

595+
/*
596+
* Many parts of Git have subprograms communicate via pipe, expect the
597+
* upstream of a pipe to die with SIGPIPE when the downstream of a
598+
* pipe does not need to read all that is written. Some third-party
599+
* programs that ignore or block SIGPIPE for their own reason forget
600+
* to restore SIGPIPE handling to the default before spawning Git and
601+
* break this carefully orchestrated machinery.
602+
*
603+
* Restore the way SIGPIPE is handled to default, which is what we
604+
* expect.
605+
*/
606+
static void restore_sigpipe_to_default(void)
607+
{
608+
sigset_t unblock;
609+
610+
sigemptyset(&unblock);
611+
sigaddset(&unblock, SIGPIPE);
612+
sigprocmask(SIG_UNBLOCK, &unblock, NULL);
613+
signal(SIGPIPE, SIG_DFL);
614+
}
595615

596616
int main(int argc, char **av)
597617
{
@@ -611,6 +631,8 @@ int main(int argc, char **av)
611631
*/
612632
sanitize_stdfds();
613633

634+
restore_sigpipe_to_default();
635+
614636
git_setup_gettext();
615637

616638
trace_command_performance(argv);

t/t0005-signals.sh

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,26 @@ test_expect_success !MINGW 'signals are propagated using shell convention' '
2727
test_expect_code 143 git sigterm
2828
'
2929

30+
large_git () {
31+
for i in $(test_seq 1 100)
32+
do
33+
git diff --cached --binary || return
34+
done
35+
}
36+
37+
test_expect_success 'create blob' '
38+
test-genrandom foo 16384 >file &&
39+
git add file
40+
'
41+
42+
test_expect_success !MINGW 'a constipated git dies with SIGPIPE' '
43+
OUT=$( ((large_git; echo $? 1>&3) | :) 3>&1 )
44+
test "$OUT" -eq 141
45+
'
46+
47+
test_expect_success !MINGW 'a constipated git dies with SIGPIPE even if parent ignores it' '
48+
OUT=$( ((trap "" PIPE; large_git; echo $? 1>&3) | :) 3>&1 )
49+
test "$OUT" -eq 141
50+
'
51+
3052
test_done

0 commit comments

Comments
 (0)