summaryrefslogtreecommitdiff
path: root/usr.bin/mandoc
diff options
context:
space:
mode:
authorIngo Schwarze <schwarze@cvs.openbsd.org>2016-04-14 20:54:16 +0000
committerIngo Schwarze <schwarze@cvs.openbsd.org>2016-04-14 20:54:16 +0000
commit26ea74e537e0b130d204678bbc73d5d536daecce (patch)
treeb24cb3d8c9cca146717035c3da3c7da9ef66fe7a /usr.bin/mandoc
parent4a2a7737fca5b3c27b3a9cb329189f803fdf968f (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.c12
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]);
}