Mercurial > hg
changeset 29429:cf99de051385
chg: send SIGPIPE to server immediately when pager exits (issue5278)
If the user press 'q' to leave the 'less' pager, it is expected to end the
hg process immediately. We currently rely on SIGPIPE for this behavior. But
SIGPIPE won't arrive if we don't write anything (like doing heavy
computation, reading from network etc). If that happens, the user will feel
that the hg process just hangs.
The patch address the issue by adding a SIGCHLD signal handler and sends
SIGPIPE to the server as soon as the pager exits.
This is also an issue with hg's pager implementation.
author | Jun Wu <quark@fb.com> |
---|---|
date | Fri, 24 Jun 2016 15:21:10 +0100 |
parents | 247ea0dfdb94 |
children | 72065b3b90a4 |
files | contrib/chg/chg.c |
diffstat | 1 files changed, 20 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- a/contrib/chg/chg.c Fri Jun 24 17:06:41 2016 +0100 +++ b/contrib/chg/chg.c Fri Jun 24 15:21:10 2016 +0100 @@ -338,6 +338,7 @@ } } +static pid_t pagerpid = 0; static pid_t peerpid = 0; static void forwardsignal(int sig) @@ -380,6 +381,17 @@ abortmsgerrno("failed to handle stop signal"); } +static void handlechildsignal(int sig) +{ + if (peerpid == 0 || pagerpid == 0) + return; + /* if pager exits, notify the server with SIGPIPE immediately. + * otherwise the server won't get SIGPIPE if it does not write + * anything. (issue5278) */ + if (waitpid(pagerpid, NULL, WNOHANG) == pagerpid) + kill(peerpid, SIGPIPE); +} + static void setupsignalhandler(pid_t pid) { if (pid <= 0) @@ -416,6 +428,11 @@ sa.sa_flags = SA_RESTART; if (sigaction(SIGTSTP, &sa, NULL) < 0) goto error; + /* get notified when pager exits */ + sa.sa_handler = handlechildsignal; + sa.sa_flags = SA_RESTART; + if (sigaction(SIGCHLD, &sa, NULL) < 0) + goto error; return; @@ -442,6 +459,8 @@ goto error; if (sigaction(SIGTSTP, &sa, NULL) < 0) goto error; + if (sigaction(SIGCHLD, &sa, NULL) < 0) + goto error; /* ignore Ctrl+C while shutting down to make pager exits cleanly */ sa.sa_handler = SIG_IGN; @@ -638,7 +657,7 @@ } setupsignalhandler(hgc_peerpid(hgc)); - pid_t pagerpid = setuppager(hgc, argv + 1, argc - 1); + pagerpid = setuppager(hgc, argv + 1, argc - 1); int exitcode = hgc_runcommand(hgc, argv + 1, argc - 1); restoresignalhandler(); hgc_close(hgc);