--- 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 */