[PATCH stable] pager: fork and exec pager as parent process
Augie Fackler
durin42 at gmail.com
Sat May 15 11:04:11 CDT 2010
This looks reasonable to me, and I don't know that I ever commented on it.
Did you ever push it?
On May 3, 2010, at 2:06 PM, Brodie Rao wrote:
> # HG changeset patch
> # User Brodie Rao <brodie at bitheap.org>
> # Date 1272913234 18000
> # Branch stable
> # Node ID d7625733fa0f33b913f7432941ba436f4645cea9
> # Parent b8d0b4721affa90241f304272e0836ba566d0b3a
> pager: fork and exec pager as parent process
>
> With the pager as the child process instead of the parent process, the
> termination of the parent Mercurial process can cause the terminal to return
> before the pager exits. Inverting the relationship prevents that issue.
>
> Platforms without fork() will continue to use util.popen().
>
> diff --git a/hgext/color.py b/hgext/color.py
> --- a/hgext/color.py
> +++ b/hgext/color.py
> @@ -333,11 +333,14 @@ def extsetup(ui):
>
> def _setupcmd(ui, cmd, table, func, effectsmap):
> '''patch in command to command table and load effect map'''
> + # check isatty() before anything else changes it (like pager)
> + isatty = sys.__stdout__.isatty()
> +
> def nocolor(orig, *args, **opts):
>
> if (opts['no_color'] or opts['color'] == 'never' or
> (opts['color'] == 'auto' and (os.environ.get('TERM') == 'dumb'
> - or not sys.__stdout__.isatty()))):
> + or not isatty))):
> del opts['no_color']
> del opts['color']
> return orig(*args, **opts)
> diff --git a/hgext/pager.py b/hgext/pager.py
> --- a/hgext/pager.py
> +++ b/hgext/pager.py
> @@ -49,9 +49,27 @@ To ignore global commands like "hg versi
> specify them in the global .hgrc
> '''
>
> -import sys, os, signal
> +import sys, os, signal, shlex
> from mercurial import dispatch, util, extensions
>
> +def _runpager(p):
> + if not hasattr(os, 'fork'):
> + sys.stderr = sys.stdout = util.popen(p, 'wb')
> + return
> + fdin, fdout = os.pipe()
> + pid = os.fork()
> + if pid == 0:
> + os.close(fdin)
> + os.dup2(fdout, sys.stdout.fileno())
> + os.dup2(fdout, sys.stderr.fileno())
> + os.close(fdout)
> + return
> + os.dup2(fdin, sys.stdin.fileno())
> + os.close(fdin)
> + os.close(fdout)
> + args = shlex.split(p)
> + os.execvp(args[0], args)
> +
> def uisetup(ui):
> def pagecmd(orig, ui, options, cmd, cmdfunc):
> p = ui.config("pager", "pager", os.environ.get("PAGER"))
> @@ -60,7 +78,7 @@ def uisetup(ui):
> if (cmd in attend or
> (cmd not in ui.configlist('pager', 'ignore') and not attend)):
> ui.setconfig('ui', 'interactive', False)
> - sys.stderr = sys.stdout = util.popen(p, "wb")
> + _runpager(p)
> if ui.configbool('pager', 'quiet'):
> signal.signal(signal.SIGPIPE, signal.SIG_DFL)
> return orig(ui, options, cmd, cmdfunc)
More information about the Mercurial-devel
mailing list