source@mandoc.bsd.lv
 help / color / mirror / Atom feed
* mdocml: Fix multiple issues regarding process group and signal mask
@ 2015-11-20 22:00 schwarze
  0 siblings, 0 replies; only message in thread
From: schwarze @ 2015-11-20 22:00 UTC (permalink / raw)
  To: source

Log Message:
-----------
Fix multiple issues regarding process group and signal mask handling
found by tb@ and millert@; parts of the code, in particular in tag.c,
by millert@; OK millert@.

Modified Files:
--------------
    mdocml:
        main.c
        tag.c
        tag.h

Revision Data
-------------
Index: tag.c
===================================================================
RCS file: /home/cvs/mdocml/mdocml/tag.c,v
retrieving revision 1.10
retrieving revision 1.11
diff -Ltag.c -Ltag.c -u -p -r1.10 -r1.11
--- tag.c
+++ tag.c
@@ -50,10 +50,12 @@ static struct tag_files	 tag_files;
 struct tag_files *
 tag_init(void)
 {
+	struct sigaction	 sa;
 	int			 ofd;
 
 	ofd = -1;
 	tag_files.tfd = -1;
+	tag_files.tcpgid = -1;
 
 	/* Save the original standard output for use by the pager. */
 
@@ -66,9 +68,12 @@ tag_init(void)
 	    sizeof(tag_files.ofn));
 	(void)strlcpy(tag_files.tfn, "/tmp/man.XXXXXXXXXX",
 	    sizeof(tag_files.tfn));
-	signal(SIGHUP, tag_signal);
-	signal(SIGINT, tag_signal);
-	signal(SIGTERM, tag_signal);
+	memset(&sa, 0, sizeof(sa));
+	sigfillset(&sa.sa_mask);
+	sa.sa_handler = tag_signal;
+	sigaction(SIGHUP, &sa, NULL);
+	sigaction(SIGINT, &sa, NULL);
+	sigaction(SIGTERM, &sa, NULL);
 	if ((ofd = mkstemp(tag_files.ofn)) == -1)
 		goto fail;
 	if ((tag_files.tfd = mkstemp(tag_files.tfn)) == -1)
@@ -156,7 +161,15 @@ tag_write(void)
 void
 tag_unlink(void)
 {
+	pid_t	 tc_pgid;
 
+	if (tag_files.tcpgid != -1) {
+		tc_pgid = tcgetpgrp(STDIN_FILENO);
+		if (tc_pgid == tag_files.pager_pid ||
+		    tc_pgid == getpgid(0) ||
+		    getpgid(tc_pgid) == -1)
+			(void)tcsetpgrp(STDIN_FILENO, tag_files.tcpgid);
+	}
 	if (*tag_files.ofn != '\0')
 		unlink(tag_files.ofn);
 	if (*tag_files.tfn != '\0')
@@ -166,9 +179,13 @@ tag_unlink(void)
 static void
 tag_signal(int signum)
 {
+	struct sigaction	 sa;
 
 	tag_unlink();
-	signal(signum, SIG_DFL);
+	memset(&sa, 0, sizeof(sa));
+	sigemptyset(&sa.sa_mask);
+	sa.sa_handler = SIG_DFL;
+	sigaction(signum, &sa, NULL);
 	kill(getpid(), signum);
 	/* NOTREACHED */
 	_exit(1);
Index: tag.h
===================================================================
RCS file: /home/cvs/mdocml/mdocml/tag.h,v
retrieving revision 1.6
retrieving revision 1.7
diff -Ltag.h -Ltag.h -u -p -r1.6 -r1.7
--- tag.h
+++ tag.h
@@ -20,6 +20,8 @@ struct	tag_files {
 	char	 tfn[20];
 	int	 ofd;
 	int	 tfd;
+	pid_t	 tcpgid;
+	pid_t	 pager_pid;
 };
 
 
Index: main.c
===================================================================
RCS file: /home/cvs/mdocml/mdocml/main.c,v
retrieving revision 1.258
retrieving revision 1.259
diff -Lmain.c -Lmain.c -u -p -r1.258 -r1.259
--- main.c
+++ main.c
@@ -132,9 +132,9 @@ main(int argc, char *argv[])
 	int		 show_usage;
 	int		 options;
 	int		 use_pager;
-	int		 status;
+	int		 status, signum;
 	int		 c;
-	pid_t		 pager_pid;
+	pid_t		 pager_pid, tc_pgid, man_pgid, pid;
 
 #if HAVE_PROGNAME
 	progname = getprogname();
@@ -530,11 +530,43 @@ out:
 	if (tag_files != NULL) {
 		fclose(stdout);
 		tag_write();
-		pager_pid = spawn_pager(tag_files);
+		man_pgid = getpgid(0);
+		tag_files->tcpgid = man_pgid == getpid() ?
+		    getpgid(getppid()) : man_pgid;
+		pager_pid = 0;
+		signum = SIGSTOP;
 		for (;;) {
-			if (waitpid(pager_pid, &status, WUNTRACED) == -1) {
-				if (errno == EINTR)
-					continue;
+
+			/* Stop here until moved to the foreground. */
+
+			tc_pgid = tcgetpgrp(STDIN_FILENO);
+			if (tc_pgid != man_pgid) {
+				if (tc_pgid == pager_pid) {
+					(void)tcsetpgrp(STDIN_FILENO,
+					    man_pgid);
+					if (signum == SIGTTIN)
+						continue;
+				} else
+					tag_files->tcpgid = tc_pgid;
+				kill(0, signum);
+				continue;
+			}
+
+			/* Once in the foreground, activate the pager. */
+
+			if (pager_pid) {
+				(void)tcsetpgrp(STDIN_FILENO, pager_pid);
+				kill(pager_pid, SIGCONT);
+			} else
+				pager_pid = spawn_pager(tag_files);
+
+			/* Wait for the pager to stop or exit. */
+
+			while ((pid = waitpid(pager_pid, &status,
+			    WUNTRACED)) == -1 && errno == EINTR)
+				continue;
+
+			if (pid == -1) {
 				warn("wait");
 				rc = MANDOCLEVEL_SYSERR;
 				break;
@@ -542,16 +574,7 @@ out:
 			if (!WIFSTOPPED(status))
 				break;
 
-			(void)tcsetpgrp(STDIN_FILENO, getpgid(0));
-			kill(0, WSTOPSIG(status));
-	
-			/*
-			 * I'm now stopped.
-			 * When getting SIGCONT, continue here:
-			 */
-
-			(void)tcsetpgrp(STDIN_FILENO, pager_pid);
-			kill(pager_pid, SIGCONT);
+			signum = WSTOPSIG(status);
 		}
 		tag_unlink();
 	}
@@ -1046,12 +1069,12 @@ spawn_pager(struct tag_files *tag_files)
 		break;
 	default:
 		(void)setpgid(pager_pid, 0);
-		if (tcsetpgrp(STDIN_FILENO, pager_pid) == -1)
-			err((int)MANDOCLEVEL_SYSERR, "tcsetpgrp");
+		(void)tcsetpgrp(STDIN_FILENO, pager_pid);
 #if HAVE_PLEDGE
 		if (pledge("stdio rpath tmppath tty proc", NULL) == -1)
 			err((int)MANDOCLEVEL_SYSERR, "pledge");
 #endif
+		tag_files->pager_pid = pager_pid;
 		return pager_pid;
 	}
 
--
 To unsubscribe send an email to source+unsubscribe@mdocml.bsd.lv

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2015-11-20 22:00 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-11-20 22:00 mdocml: Fix multiple issues regarding process group and signal mask schwarze

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).