From b5bf8afcdb00cf4d6cc3b38b0ec2f6c184ebc2c3 Mon Sep 17 00:00:00 2001 From: Ingo Schwarze Date: Thu, 14 Apr 2016 20:55:48 +0000 Subject: 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@. --- main.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/main.c b/main.c index 94b591ff..eb056230 100644 --- a/main.c +++ b/main.c @@ -1,4 +1,4 @@ -/* $Id: main.c,v 1.264 2016/04/13 12:26:25 schwarze Exp $ */ +/* $Id: main.c,v 1.265 2016/04/14 20:55:48 schwarze Exp $ */ /* * Copyright (c) 2008-2012 Kristaps Dzonsons * Copyright (c) 2010-2012, 2014-2016 Ingo Schwarze @@ -35,6 +35,7 @@ #include #include #include +#include #include #include "mandoc_aux.h" @@ -1020,6 +1021,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; @@ -1069,8 +1071,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); @@ -1089,6 +1089,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]); } -- cgit v1.2.3-56-ge451