diff options
author | Ingo Schwarze <schwarze@cvs.openbsd.org> | 2016-04-14 20:54:16 +0000 |
---|---|---|
committer | Ingo Schwarze <schwarze@cvs.openbsd.org> | 2016-04-14 20:54:16 +0000 |
commit | 26ea74e537e0b130d204678bbc73d5d536daecce (patch) | |
tree | b24cb3d8c9cca146717035c3da3c7da9ef66fe7a /usr.bin/mandoc | |
parent | 4a2a7737fca5b3c27b3a9cb329189f803fdf968f (diff) |
Fix a process group race.
It could occasionally happen that the child process spawned less(1)
before the parent process passed the control of the terminal to the
child, and in that case, less(1) sometimes complained "Stopped (tty
output)". Issue reported by naddy@.
Diffstat (limited to 'usr.bin/mandoc')
-rw-r--r-- | usr.bin/mandoc/main.c | 12 |
1 files changed, 9 insertions, 3 deletions
diff --git a/usr.bin/mandoc/main.c b/usr.bin/mandoc/main.c index 0c3100ee325..8cadeef4eac 100644 --- a/usr.bin/mandoc/main.c +++ b/usr.bin/mandoc/main.c @@ -1,4 +1,4 @@ -/* $OpenBSD: main.c,v 1.171 2016/04/13 12:26:21 schwarze Exp $ */ +/* $OpenBSD: main.c,v 1.172 2016/04/14 20:54:15 schwarze Exp $ */ /* * Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2010-2012, 2014-2016 Ingo Schwarze <schwarze@openbsd.org> @@ -32,6 +32,7 @@ #include <stdint.h> #include <stdlib.h> #include <string.h> +#include <time.h> #include <unistd.h> #include "mandoc_aux.h" @@ -975,6 +976,7 @@ mmsg(enum mandocerr t, enum mandoclevel lvl, static pid_t spawn_pager(struct tag_files *tag_files) { + const struct timespec timeout = { 0, 100000000 }; /* 0.1s */ #define MAX_PAGER_ARGS 16 char *argv[MAX_PAGER_ARGS]; const char *pager; @@ -1024,8 +1026,6 @@ spawn_pager(struct tag_files *tag_files) case -1: err((int)MANDOCLEVEL_SYSERR, "fork"); case 0: - /* Set pgrp in both parent and child to avoid racing exec. */ - (void)setpgid(0, 0); break; default: (void)setpgid(pager_pid, 0); @@ -1042,6 +1042,12 @@ spawn_pager(struct tag_files *tag_files) err((int)MANDOCLEVEL_SYSERR, "pager stdout"); close(tag_files->ofd); close(tag_files->tfd); + + /* Do not start the pager before controlling the terminal. */ + + while (tcgetpgrp(STDIN_FILENO) != getpid()) + nanosleep(&timeout, NULL); + execvp(argv[0], argv); err((int)MANDOCLEVEL_SYSERR, "exec %s", argv[0]); } |