Patchwork [3,of,3] dispatch: do not close stdout and stderr, just flush() instead

login
register
mail settings
Submitter Yuya Nishihara
Date June 5, 2017, 3:23 p.m.
Message ID <7fc71d7e74370f62e04e.1496676210@mimosa>
Download mbox | patch
Permalink /patch/21209/
State Accepted
Headers show

Comments

Yuya Nishihara - June 5, 2017, 3:23 p.m.
# HG changeset patch
# User Yuya Nishihara <yuya@tcha.org>
# Date 1492875089 -32400
#      Sun Apr 23 00:31:29 2017 +0900
# Node ID 7fc71d7e74370f62e04e38c20337861732edbc98
# Parent  53953046e8e443c31fbe1a9b94e8b95e92f6bda6
dispatch: do not close stdout and stderr, just flush() instead

Since 3a4c0905f357 "util: always force line buffered stdout when stdout is
a tty", we have two file objects attached to the same STDOUT_FILENO. If one
is closed, the underlying file descriptor is also closed, and writing to
the other file object would crash the Python interpreter in a hard way, at
least on Windows.

So, it seems safer to not close the standard streams. This also matches
the behavior of the default sys.stdout/stderr.close(), which never close
the FILE* streams in C layer.

https://hg.python.org/cpython/file/v2.7.13/Python/sysmodule.c#l1401
Augie Fackler - June 5, 2017, 6:12 p.m.
On Tue, Jun 06, 2017 at 12:23:30AM +0900, Yuya Nishihara wrote:
> # HG changeset patch
> # User Yuya Nishihara <yuya@tcha.org>
> # Date 1492875089 -32400
> #      Sun Apr 23 00:31:29 2017 +0900
> # Node ID 7fc71d7e74370f62e04e38c20337861732edbc98
> # Parent  53953046e8e443c31fbe1a9b94e8b95e92f6bda6
> dispatch: do not close stdout and stderr, just flush() instead

queued, thanks

Patch

diff --git a/mercurial/dispatch.py b/mercurial/dispatch.py
--- a/mercurial/dispatch.py
+++ b/mercurial/dispatch.py
@@ -88,13 +88,13 @@  def run():
         status = -1
     if util.safehasattr(req.ui, 'fout'):
         try:
-            req.ui.fout.close()
+            req.ui.fout.flush()
         except IOError as err:
             status = -1
     if util.safehasattr(req.ui, 'ferr'):
         if err is not None and err.errno != errno.EPIPE:
             req.ui.ferr.write('abort: %s\n' % err.strerror)
-        req.ui.ferr.close()
+        req.ui.ferr.flush()
     sys.exit(status & 255)
 
 def _getsimilar(symbols, value):