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().
--- a/hgext/color.py Thu May 13 11:30:50 2010 -0500
+++ b/hgext/color.py Mon May 03 14:00:34 2010 -0500
@@ -333,11 +333,14 @@
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)
--- a/hgext/pager.py Thu May 13 11:30:50 2010 -0500
+++ b/hgext/pager.py Mon May 03 14:00:34 2010 -0500
@@ -49,9 +49,27 @@
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 @@
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)