pager: do wait_for_pager on signal death

Since ea27a18 (spawn pager via run_command interface), the
original git process actually does git work, and the pager
is a child process (actually, on Windows it has always been
that way, since Windows lacks fork). After spawning the
pager, we register an atexit() handler that waits for the
pager to finish.

Unfortunately, that handler does not always run. In
particular, if git is killed by a signal, then we exit
immediately. The calling shell then thinks that git is done;
however, the pager is still trying to run and impact the
terminal. The result can be seen by running a long git
process with a pager (e.g., "git log -p") and hitting ^C.
Depending on your config, you should see the shell prompt,
but pressing a key causes the pager to do any terminal
de-initialization sequence.

This patch just intercepts any death-dealing signals and
waits for the pager before dying. Under typical less
configuration, that means hitting ^C will cause git to stop
generating output, but the pager will keep running.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Jeff King 2009-01-22 01:03:28 -05:00 коммит произвёл Junio C Hamano
Родитель 57b235a4bc
Коммит a3da882120
1 изменённых файлов: 9 добавлений и 0 удалений

Просмотреть файл

@ -1,5 +1,6 @@
#include "cache.h" #include "cache.h"
#include "run-command.h" #include "run-command.h"
#include "sigchain.h"
/* /*
* This is split up from the rest of git so that we can do * This is split up from the rest of git so that we can do
@ -38,6 +39,13 @@ static void wait_for_pager(void)
finish_command(&pager_process); finish_command(&pager_process);
} }
static void wait_for_pager_signal(int signo)
{
wait_for_pager();
sigchain_pop(signo);
raise(signo);
}
void setup_pager(void) void setup_pager(void)
{ {
const char *pager = getenv("GIT_PAGER"); const char *pager = getenv("GIT_PAGER");
@ -75,6 +83,7 @@ void setup_pager(void)
close(pager_process.in); close(pager_process.in);
/* this makes sure that the parent terminates after the pager */ /* 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);
} }