[PATCH 3 of 3] chg: forward SIGINT, SIGHUP to process group

Jun Wu quark at fb.com
Sun Jul 17 18:09:43 EDT 2016


# HG changeset patch
# User Jun Wu <quark at fb.com>
# Date 1468792547 -3600
#      Sun Jul 17 22:55:47 2016 +0100
# Node ID a655c2315828c82ef6ca33cbde254031a3ca89e2
# Parent  57234c11a5d542865e7360b7b943793e4fd110f7
# Available At https://bitbucket.org/quark-zju/hg-draft
#              hg pull https://bitbucket.org/quark-zju/hg-draft -r a655c2315828
chg: forward SIGINT, SIGHUP to process group

These signals are meant to send to a process group, instead of a single
process.

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.

diff --git a/contrib/chg/chg.c b/contrib/chg/chg.c
--- a/contrib/chg/chg.c
+++ b/contrib/chg/chg.c
@@ -339,6 +339,7 @@ static void killcmdserver(const struct c
 }
 
 static pid_t pagerpid = 0;
+static pid_t peerpgid = 0;
 static pid_t peerpid = 0;
 
 static void forwardsignal(int sig)
@@ -349,6 +350,15 @@ static void forwardsignal(int sig)
 	debugmsg("forward signal %d", sig);
 }
 
+static void forwardsignaltogroup(int sig)
+{
+	/* prefer kill(-pgid, sig) but use pid if pgid is unavailable */
+	pid_t killpid = peerpgid ? -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,16 @@ static void handlechildsignal(int sig UN
 		kill(peerpid, SIGPIPE);
 }
 
-static void setupsignalhandler(pid_t pid)
+static void setupsignalhandler(const hgclient_t *hgc)
 {
-	if (pid <= 0)
+	peerpgid = hgc_peerpgid(hgc);
+	peerpid = hgc_peerpid(hgc);
+	if (peerpgid <= 0 && peerpid <= 0)
 		return;
-	peerpid = pid;
 
 	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 +422,7 @@ static void setupsignalhandler(pid_t pid
 		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 +668,7 @@ int main(int argc, const char *argv[], c
 				 gethgcmd());
 	}
 
-	setupsignalhandler(hgc_peerpid(hgc));
+	setupsignalhandler(hgc);
 	pagerpid = setuppager(hgc, argv + 1, argc - 1);
 	int exitcode = hgc_runcommand(hgc, argv + 1, argc - 1);
 	restoresignalhandler();


More information about the Mercurial-devel mailing list