From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from localhost (fantadrom.bsd.lv [local]) by fantadrom.bsd.lv (OpenSMTPD) with ESMTPA id 3be9706c for ; Fri, 20 Nov 2015 17:00:24 -0500 (EST) Date: Fri, 20 Nov 2015 17:00:24 -0500 (EST) Message-Id: <12527638429202322735.enqueue@fantadrom.bsd.lv> X-Mailinglist: mdocml-source Reply-To: source@mdocml.bsd.lv MIME-Version: 1.0 From: schwarze@mdocml.bsd.lv To: source@mdocml.bsd.lv Subject: mdocml: Fix multiple issues regarding process group and signal mask X-Mailer: activitymail 1.26, http://search.cpan.org/dist/activitymail/ Content-Type: text/plain; charset=utf-8 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