Skip to content

Commit

Permalink
Merge branch 'pr/use-default-sigpipe-setting'
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Junio C Hamano committed Sep 30, 2014
2 parents 0bf7dd6 + 4e6d207 commit 131f031
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 1 deletion.
7 changes: 6 additions & 1 deletion compat/mingw.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@ struct sigaction {
sig_handler_t sa_handler;
unsigned sa_flags;
};
#define sigemptyset(x) (void)0
#define SA_RESTART 0

struct itimerval {
Expand Down Expand Up @@ -116,6 +115,12 @@ static inline int fcntl(int fd, int cmd, ...)
}
/* bash cannot reliably detect negative return codes as failure */
#define exit(code) exit((code) & 0xff)
#define sigemptyset(x) (void)0
static inline int sigaddset(sigset_t *set, int signum)
{ return 0; }
#define SIG_UNBLOCK 0
static inline int sigprocmask(int how, const sigset_t *set, sigset_t *oldset)
{ return 0; }

/*
* simple adaptors
Expand Down
22 changes: 22 additions & 0 deletions git.c
Original file line number Diff line number Diff line change
Expand Up @@ -592,6 +592,26 @@ static int run_argv(int *argcp, const char ***argv)
return done_alias;
}

/*
* Many parts of Git have subprograms communicate via pipe, expect the
* upstream of a pipe to die with SIGPIPE when the downstream of a
* pipe does not need to read all that is written. Some third-party
* programs that ignore or block SIGPIPE for their own reason forget
* to restore SIGPIPE handling to the default before spawning Git and
* break this carefully orchestrated machinery.
*
* Restore the way SIGPIPE is handled to default, which is what we
* expect.
*/
static void restore_sigpipe_to_default(void)
{
sigset_t unblock;

sigemptyset(&unblock);
sigaddset(&unblock, SIGPIPE);
sigprocmask(SIG_UNBLOCK, &unblock, NULL);
signal(SIGPIPE, SIG_DFL);
}

int main(int argc, char **av)
{
Expand All @@ -611,6 +631,8 @@ int main(int argc, char **av)
*/
sanitize_stdfds();

restore_sigpipe_to_default();

git_setup_gettext();

trace_command_performance(argv);
Expand Down
22 changes: 22 additions & 0 deletions t/t0005-signals.sh
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,26 @@ test_expect_success !MINGW 'signals are propagated using shell convention' '
test_expect_code 143 git sigterm
'

large_git () {
for i in $(test_seq 1 100)
do
git diff --cached --binary || return
done
}

test_expect_success 'create blob' '
test-genrandom foo 16384 >file &&
git add file
'

test_expect_success !MINGW 'a constipated git dies with SIGPIPE' '
OUT=$( ((large_git; echo $? 1>&3) | :) 3>&1 )
test "$OUT" -eq 141
'

test_expect_success !MINGW 'a constipated git dies with SIGPIPE even if parent ignores it' '
OUT=$( ((trap "" PIPE; large_git; echo $? 1>&3) | :) 3>&1 )
test "$OUT" -eq 141
'

test_done

0 comments on commit 131f031

Please sign in to comment.