contrib/chg/chg.c
changeset 30689 9fa7255d4abd
parent 30681 0064a1eb28e2
child 30690 e9ec42634ec8
--- a/contrib/chg/chg.c	Wed Oct 07 16:02:45 2015 -0700
+++ b/contrib/chg/chg.c	Mon Jan 02 14:02:47 2017 +0000
@@ -303,214 +303,7 @@
 	}
 }
 
-static pid_t pagerpid = 0;
-static pid_t peerpgid = 0;
-static pid_t peerpid = 0;
-
-static void forwardsignal(int sig)
-{
-	assert(peerpid > 0);
-	if (kill(peerpid, sig) < 0)
-		abortmsgerrno("cannot kill %d", peerpid);
-	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;
-	struct sigaction sa, oldsa;
-	if (sigemptyset(&unblockset) < 0)
-		goto error;
-	if (sigaddset(&unblockset, sig) < 0)
-		goto error;
-	memset(&sa, 0, sizeof(sa));
-	sa.sa_handler = SIG_DFL;
-	sa.sa_flags = SA_RESTART;
-	if (sigemptyset(&sa.sa_mask) < 0)
-		goto error;
-
-	forwardsignal(sig);
-	if (raise(sig) < 0)  /* resend to self */
-		goto error;
-	if (sigaction(sig, &sa, &oldsa) < 0)
-		goto error;
-	if (sigprocmask(SIG_UNBLOCK, &unblockset, &oldset) < 0)
-		goto error;
-	/* resent signal will be handled before sigprocmask() returns */
-	if (sigprocmask(SIG_SETMASK, &oldset, NULL) < 0)
-		goto error;
-	if (sigaction(sig, &oldsa, NULL) < 0)
-		goto error;
-	return;
-
-error:
-	abortmsgerrno("failed to handle stop signal");
-}
-
-static void handlechildsignal(int sig UNUSED_)
-{
-	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(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 = forwardsignaltogroup;
-	sa.sa_flags = SA_RESTART;
-	if (sigemptyset(&sa.sa_mask) < 0)
-		goto error;
-
-	if (sigaction(SIGHUP, &sa, NULL) < 0)
-		goto error;
-	if (sigaction(SIGINT, &sa, NULL) < 0)
-		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;
-
-	/* notify the worker about window resize events */
-	sa.sa_flags = SA_RESTART;
-	if (sigaction(SIGWINCH, &sa, NULL) < 0)
-		goto error;
-	/* propagate job control requests to worker */
-	sa.sa_handler = forwardsignal;
-	sa.sa_flags = SA_RESTART;
-	if (sigaction(SIGCONT, &sa, NULL) < 0)
-		goto error;
-	sa.sa_handler = handlestopsignal;
-	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;
-
-error:
-	abortmsgerrno("failed to set up signal handlers");
-}
-
-static void restoresignalhandler()
-{
-	struct sigaction sa;
-	memset(&sa, 0, sizeof(sa));
-	sa.sa_handler = SIG_DFL;
-	sa.sa_flags = SA_RESTART;
-	if (sigemptyset(&sa.sa_mask) < 0)
-		goto error;
-
-	if (sigaction(SIGHUP, &sa, NULL) < 0)
-		goto error;
-	if (sigaction(SIGTERM, &sa, NULL) < 0)
-		goto error;
-	if (sigaction(SIGWINCH, &sa, NULL) < 0)
-		goto error;
-	if (sigaction(SIGCONT, &sa, NULL) < 0)
-		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;
-	if (sigaction(SIGINT, &sa, NULL) < 0)
-		goto error;
-
-	peerpid = 0;
-	return;
-
-error:
-	abortmsgerrno("failed to restore signal handlers");
-}
-
-/* This implementation is based on hgext/pager.py (post 369741ef7253)
- * Return 0 if pager is not started, or pid of the pager */
-static pid_t setuppager(hgclient_t *hgc, const char *const args[],
-		       size_t argsize)
-{
-	const char *pagercmd = hgc_getpager(hgc, args, argsize);
-	if (!pagercmd)
-		return 0;
-
-	int pipefds[2];
-	if (pipe(pipefds) < 0)
-		return 0;
-	pid_t pid = fork();
-	if (pid < 0)
-		goto error;
-	if (pid > 0) {
-		close(pipefds[0]);
-		if (dup2(pipefds[1], fileno(stdout)) < 0)
-			goto error;
-		if (isatty(fileno(stderr))) {
-			if (dup2(pipefds[1], fileno(stderr)) < 0)
-				goto error;
-		}
-		close(pipefds[1]);
-		hgc_attachio(hgc);  /* reattach to pager */
-		return pid;
-	} else {
-		dup2(pipefds[0], fileno(stdin));
-		close(pipefds[0]);
-		close(pipefds[1]);
-
-		int r = execlp("/bin/sh", "/bin/sh", "-c", pagercmd, NULL);
-		if (r < 0) {
-			abortmsgerrno("cannot start pager '%s'", pagercmd);
-		}
-		return 0;
-	}
-
-error:
-	close(pipefds[0]);
-	close(pipefds[1]);
-	abortmsgerrno("failed to prepare pager");
-	return 0;
-}
-
-static void waitpager(pid_t pid)
-{
-	/* close output streams to notify the pager its input ends */
-	fclose(stdout);
-	fclose(stderr);
-	while (1) {
-		pid_t ret = waitpid(pid, NULL, 0);
-		if (ret == -1 && errno == EINTR)
-			continue;
-		break;
-	}
-}
+#include "procutil.c"
 
 /* Run instructions sent from the server like unlink and set redirect path
  * Return 1 if reconnect is needed, otherwise 0 */