diff options
author | Junio C Hamano <gitster@pobox.com> | 2015-10-07 13:38:16 -0700 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2015-10-07 13:38:16 -0700 |
commit | 2b72dbbcf3a1d6c6813db2c13afaa1d0d8585f7b (patch) | |
tree | 2f81c60d1cecda69be7d189aba6ab99f333efc2d /pager.c | |
parent | 24a00ef646974be49ef7138239c3803805400797 (diff) | |
parent | 507d7804c0b094889cd20f23ad9a48e2b76791f3 (diff) | |
download | git-2b72dbbcf3a1d6c6813db2c13afaa1d0d8585f7b.tar.gz |
Merge branch 'ti/glibc-stdio-mutex-from-signal-handler'
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) |