Mercurial > hg
changeset 29608:681fe090d82e stable
chg: forward SIGINT, SIGHUP to process group
These signals are meant to send to a process group, instead of a single
process: SIGINT is usually emitted by the terminal and sent to the process
group. SIGHUP usually happens to a process group if termination of a process
causes that process group to become orphaned.
Before this patch, chg will only forward these signals to the single server
process. This patch changes it to the server process group.
This will allow us to properly kill processes started by the forked server
process, like a ssh process. The behavior difference can be observed by
setting SSH_ASKPASS to a dummy script doing "sleep 100" and then run
"chg push ssh://dest-need-password-auth". Before this patch, the first Ctrl+C
will kill the hg process while ssh-askpass and ssh will remain alive. This
patch will make sure they are killed properly.
author | Jun Wu <quark@fb.com> |
---|---|
date | Sun, 17 Jul 2016 22:55:47 +0100 |
parents | 02a8fea4289b |
children | 591c3badff2e |
files | contrib/chg/chg.c |
diffstat | 1 files changed, 18 insertions(+), 3 deletions(-) [+] |
line wrap: on
line diff
--- a/contrib/chg/chg.c Mon Jul 18 23:31:51 2016 -0500 +++ b/contrib/chg/chg.c Sun Jul 17 22:55:47 2016 +0100 @@ -339,6 +339,7 @@ } static pid_t pagerpid = 0; +static pid_t peerpgid = 0; static pid_t peerpid = 0; static void forwardsignal(int sig) @@ -349,6 +350,15 @@ debugmsg("forward signal %d", sig); } +static void forwardsignaltogroup(int sig) +{ + /* prefer kill(-pgid, sig), fallback to pid if pgid is invalid */ + pid_t killpid = peerpgid > 1 ? -peerpgid : peerpid; + if (kill(killpid, sig) < 0) + abortmsgerrno("cannot kill %d", killpid); + debugmsg("forward signal %d to %d", sig, killpid); +} + static void handlestopsignal(int sig) { sigset_t unblockset, oldset; @@ -392,15 +402,19 @@ kill(peerpid, SIGPIPE); } -static void setupsignalhandler(pid_t pid) +static void setupsignalhandler(const hgclient_t *hgc) { + pid_t pid = hgc_peerpid(hgc); if (pid <= 0) return; peerpid = pid; + pid_t pgid = hgc_peerpgid(hgc); + peerpgid = (pgid <= 1 ? 0 : pgid); + struct sigaction sa; memset(&sa, 0, sizeof(sa)); - sa.sa_handler = forwardsignal; + sa.sa_handler = forwardsignaltogroup; sa.sa_flags = SA_RESTART; if (sigemptyset(&sa.sa_mask) < 0) goto error; @@ -411,6 +425,7 @@ goto error; /* terminate frontend by double SIGTERM in case of server freeze */ + sa.sa_handler = forwardsignal; sa.sa_flags |= SA_RESETHAND; if (sigaction(SIGTERM, &sa, NULL) < 0) goto error; @@ -656,7 +671,7 @@ gethgcmd()); } - setupsignalhandler(hgc_peerpid(hgc)); + setupsignalhandler(hgc); pagerpid = setuppager(hgc, argv + 1, argc - 1); int exitcode = hgc_runcommand(hgc, argv + 1, argc - 1); restoresignalhandler();