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);