diff options
author | Junio C Hamano <gitster@pobox.com> | 2015-10-16 14:32:41 -0700 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2015-10-16 14:32:41 -0700 |
commit | 267ebf6c84eb4437c219c16848678b090b4af6e2 (patch) | |
tree | b17c55b198e26df951cf556162775dd68765f688 /pager.c | |
parent | f4892a3c2883bd517edf370c747afde29a0c2b3c (diff) | |
parent | 507d7804c0b094889cd20f23ad9a48e2b76791f3 (diff) | |
download | git-267ebf6c84eb4437c219c16848678b090b4af6e2.tar.gz |
Merge branch 'ti/glibc-stdio-mutex-from-signal-handler' into maint
Allocation related functions and stdio are unsafe things to call
inside a signal handler, and indeed killing the pager can cause
glibc to deadlock waiting on allocation mutex as our signal handler
tries to free() some data structures in wait_for_pager(). Reduce
these unsafe calls.
* ti/glibc-stdio-mutex-from-signal-handler:
pager: don't use unsafe functions in signal handlers
Diffstat (limited to 'pager.c')
-rw-r--r-- | pager.c | 22 |
1 files changed, 16 insertions, 6 deletions
@@ -14,19 +14,29 @@ static const char *pager_argv[] = { NULL, NULL }; static struct child_process pager_process = CHILD_PROCESS_INIT; -static void wait_for_pager(void) +static void wait_for_pager(int in_signal) { - fflush(stdout); - fflush(stderr); + if (!in_signal) { + fflush(stdout); + fflush(stderr); + } /* signal EOF to pager */ close(1); close(2); - finish_command(&pager_process); + if (in_signal) + finish_command_in_signal(&pager_process); + else + finish_command(&pager_process); +} + +static void wait_for_pager_atexit(void) +{ + wait_for_pager(0); } static void wait_for_pager_signal(int signo) { - wait_for_pager(); + wait_for_pager(1); sigchain_pop(signo); raise(signo); } @@ -90,7 +100,7 @@ void setup_pager(void) /* this makes sure that the parent terminates after the pager */ sigchain_push_common(wait_for_pager_signal); - atexit(wait_for_pager); + atexit(wait_for_pager_atexit); } int pager_in_use(void) |