Mercurial > hg
comparison hgext/pager.py @ 30876:3a4c0905f357
util: always force line buffered stdout when stdout is a tty (BC)
pager replaced stdout with a line buffered version to work around glibc
deciding on a buffering strategy on the first write to stdout. This is going
to make my next patch hard, as replacing stdout will make tracking time
spent blocked on it more challenging.
Move the line buffering requirement to util.py, and remove it from pager.
This means that the abuse of ui.formatted=True and pager set to cat or equivalent
no longer results in a line-buffered output to a pipe, hence (BC), although
I don't expect anyone to be affected
author | Simon Farnsworth <simonfar@fb.com> |
---|---|
date | Fri, 03 Feb 2017 15:10:27 -0800 |
parents | aaa751585325 |
children | 253d5c0f3a2f |
comparison
equal
deleted
inserted
replaced
30875:1791be8a95c5 | 30876:3a4c0905f357 |
---|---|
85 def _runpager(ui, p): | 85 def _runpager(ui, p): |
86 pager = subprocess.Popen(p, shell=True, bufsize=-1, | 86 pager = subprocess.Popen(p, shell=True, bufsize=-1, |
87 close_fds=util.closefds, stdin=subprocess.PIPE, | 87 close_fds=util.closefds, stdin=subprocess.PIPE, |
88 stdout=util.stdout, stderr=util.stderr) | 88 stdout=util.stdout, stderr=util.stderr) |
89 | 89 |
90 # back up original file objects and descriptors | 90 # back up original file descriptors |
91 olduifout = ui.fout | |
92 oldstdout = util.stdout | |
93 stdoutfd = os.dup(util.stdout.fileno()) | 91 stdoutfd = os.dup(util.stdout.fileno()) |
94 stderrfd = os.dup(util.stderr.fileno()) | 92 stderrfd = os.dup(util.stderr.fileno()) |
95 | 93 |
96 # create new line-buffered stdout so that output can show up immediately | |
97 ui.fout = util.stdout = newstdout = os.fdopen(util.stdout.fileno(), 'wb', 1) | |
98 os.dup2(pager.stdin.fileno(), util.stdout.fileno()) | 94 os.dup2(pager.stdin.fileno(), util.stdout.fileno()) |
99 if ui._isatty(util.stderr): | 95 if ui._isatty(util.stderr): |
100 os.dup2(pager.stdin.fileno(), util.stderr.fileno()) | 96 os.dup2(pager.stdin.fileno(), util.stderr.fileno()) |
101 | 97 |
102 @atexit.register | 98 @atexit.register |
103 def killpager(): | 99 def killpager(): |
104 if util.safehasattr(signal, "SIGINT"): | 100 if util.safehasattr(signal, "SIGINT"): |
105 signal.signal(signal.SIGINT, signal.SIG_IGN) | 101 signal.signal(signal.SIGINT, signal.SIG_IGN) |
106 pager.stdin.close() | 102 # restore original fds, closing pager.stdin copies in the process |
107 ui.fout = olduifout | |
108 util.stdout = oldstdout | |
109 # close new stdout while it's associated with pager; otherwise stdout | |
110 # fd would be closed when newstdout is deleted | |
111 newstdout.close() | |
112 # restore original fds: stdout is open again | |
113 os.dup2(stdoutfd, util.stdout.fileno()) | 103 os.dup2(stdoutfd, util.stdout.fileno()) |
114 os.dup2(stderrfd, util.stderr.fileno()) | 104 os.dup2(stderrfd, util.stderr.fileno()) |
105 pager.stdin.close() | |
115 pager.wait() | 106 pager.wait() |
116 | 107 |
117 def uisetup(ui): | 108 def uisetup(ui): |
118 class pagerui(ui.__class__): | 109 class pagerui(ui.__class__): |
119 def _runpager(self, pagercmd): | 110 def _runpager(self, pagercmd): |