diff --git a/fetch-pack.c b/fetch-pack.c
index 01e34b689b..f96f6dfb35 100644
--- a/fetch-pack.c
+++ b/fetch-pack.c
@@ -15,6 +15,7 @@
 #include "version.h"
 #include "prio-queue.h"
 #include "sha1-array.h"
+#include "sigchain.h"
 
 static int transfer_unpack_limit = -1;
 static int fetch_unpack_limit = -1;
@@ -671,9 +672,12 @@ static int everything_local(struct fetch_pack_args *args,
 static int sideband_demux(int in, int out, void *data)
 {
 	int *xd = data;
+	int ret;
 
-	int ret = recv_sideband("fetch-pack", xd[0], out);
+	sigchain_push(SIGPIPE, SIG_IGN);
+	ret = recv_sideband("fetch-pack", xd[0], out);
 	close(out);
+	sigchain_pop(SIGPIPE);
 	return ret;
 }
 
diff --git a/run-command.c b/run-command.c
index 13fa452e8c..3add1d66ac 100644
--- a/run-command.c
+++ b/run-command.c
@@ -633,6 +633,11 @@ int in_async(void)
 	return !pthread_equal(main_thread, pthread_self());
 }
 
+void NORETURN async_exit(int code)
+{
+	pthread_exit((void *)(intptr_t)code);
+}
+
 #else
 
 static struct {
@@ -678,6 +683,11 @@ int in_async(void)
 	return process_is_async;
 }
 
+void NORETURN async_exit(int code)
+{
+	exit(code);
+}
+
 #endif
 
 int start_async(struct async *async)
diff --git a/run-command.h b/run-command.h
index 12bb26c2a6..c0969c7695 100644
--- a/run-command.h
+++ b/run-command.h
@@ -121,5 +121,6 @@ struct async {
 int start_async(struct async *async);
 int finish_async(struct async *async);
 int in_async(void);
+void NORETURN async_exit(int code);
 
 #endif
diff --git a/t/t5504-fetch-receive-strict.sh b/t/t5504-fetch-receive-strict.sh
index 89224edcc5..a3e12d295a 100755
--- a/t/t5504-fetch-receive-strict.sh
+++ b/t/t5504-fetch-receive-strict.sh
@@ -101,7 +101,10 @@ test_expect_success 'push with receive.fsckobjects' '
 		git config transfer.fsckobjects false
 	) &&
 	test_must_fail ok=sigpipe git push --porcelain dst master:refs/heads/test >act &&
-	test_cmp exp act
+	{
+		test_cmp exp act ||
+		! test -s act
+	}
 '
 
 test_expect_success 'push with transfer.fsckobjects' '
diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
index c64e5a5025..8d99eb303f 100644
--- a/t/test-lib-functions.sh
+++ b/t/test-lib-functions.sh
@@ -617,7 +617,7 @@ test_must_fail () {
 		return 0
 	elif test $exit_code -gt 129 && test $exit_code -le 192
 	then
-		echo >&2 "test_must_fail: died by signal: $*"
+		echo >&2 "test_must_fail: died by signal $(($exit_code - 128)): $*"
 		return 1
 	elif test $exit_code -eq 127
 	then
diff --git a/write_or_die.c b/write_or_die.c
index e7afe7a295..49e80aa222 100644
--- a/write_or_die.c
+++ b/write_or_die.c
@@ -1,8 +1,12 @@
 #include "cache.h"
+#include "run-command.h"
 
 static void check_pipe(int err)
 {
 	if (err == EPIPE) {
+		if (in_async())
+			async_exit(141);
+
 		signal(SIGPIPE, SIG_DFL);
 		raise(SIGPIPE);
 		/* Should never happen, but just in case... */