Skip to content

Commit 9658846

Browse files
peffgitster
authored andcommitted
write_or_die: handle EPIPE in async threads
When write_or_die() sees EPIPE, it treats it specially by converting it into a SIGPIPE death. We obviously cannot ignore it, as the write has failed and the caller expects us to die. But likewise, we cannot just call die(), because printing any message at all would be a nuisance during normal operations. However, this is a problem if write_or_die() is called from a thread. Our raised signal ends up killing the whole process, when logically we just need to kill the thread (after all, if we are ignoring SIGPIPE, there is good reason to think that the main thread is expecting to handle it). Inside an async thread, the die() code already does the right thing, because we use our custom die_async() routine, which calls pthread_join(). So ideally we would piggy-back on that, and simply call: die_quietly_with_code(141); or similar. But refactoring the die code to do this is surprisingly non-trivial. The die_routines themselves handle both printing and the decision of the exit code. Every one of them would have to be modified to take new parameters for the code, and to tell us to be quiet. Instead, we can just teach write_or_die() to check for the async case and handle it specially. We do have to build an interface to abstract the async exit, but it's simple and self-contained. If we had many call-sites that wanted to do this die_quietly_with_code(), this approach wouldn't scale as well, but we don't. This is the only place where do this weird exit trick. Signed-off-by: Jeff King <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 326e5bc commit 9658846

File tree

3 files changed

+15
-0
lines changed

3 files changed

+15
-0
lines changed

run-command.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -633,6 +633,11 @@ int in_async(void)
633633
return !pthread_equal(main_thread, pthread_self());
634634
}
635635

636+
void NORETURN async_exit(int code)
637+
{
638+
pthread_exit((void *)(intptr_t)code);
639+
}
640+
636641
#else
637642

638643
static struct {
@@ -678,6 +683,11 @@ int in_async(void)
678683
return process_is_async;
679684
}
680685

686+
void NORETURN async_exit(int code)
687+
{
688+
exit(code);
689+
}
690+
681691
#endif
682692

683693
int start_async(struct async *async)

run-command.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,5 +121,6 @@ struct async {
121121
int start_async(struct async *async);
122122
int finish_async(struct async *async);
123123
int in_async(void);
124+
void NORETURN async_exit(int code);
124125

125126
#endif

write_or_die.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
#include "cache.h"
2+
#include "run-command.h"
23

34
static void check_pipe(int err)
45
{
56
if (err == EPIPE) {
7+
if (in_async())
8+
async_exit(141);
9+
610
signal(SIGPIPE, SIG_DFL);
711
raise(SIGPIPE);
812
/* Should never happen, but just in case... */

0 commit comments

Comments
 (0)