Patchwork [2,of,3] py3: silence the final IOError by closing stdout/err slightly early

login
register
mail settings
Submitter Yuya Nishihara
Date March 3, 2018, 3:52 a.m.
Message ID <93fda19cf79e6f5d40b2.1520049155@mimosa>
Download mbox | patch
Permalink /patch/28763/
State Accepted
Headers show

Comments

Yuya Nishihara - March 3, 2018, 3:52 a.m.
# HG changeset patch
# User Yuya Nishihara <yuya@tcha.org>
# Date 1520048120 18000
#      Fri Mar 02 22:35:20 2018 -0500
# Node ID 93fda19cf79e6f5d40b27720a0d65cd862f3a9f9
# Parent  c0193f6ec467af81491d0e7c8c46fe0f676f3018
py3: silence the final IOError by closing stdout/err slightly early

Fixes the following test failure:

  $ hg status >/dev/full
  abort: No space left on device
  Exception ignored in: <_io.TextIOWrapper name='<stdout>' mode='w' ...
  OSError: [Errno 28] No space left on device
  [120]

Patch

diff --git a/mercurial/dispatch.py b/mercurial/dispatch.py
--- a/mercurial/dispatch.py
+++ b/mercurial/dispatch.py
@@ -105,16 +105,38 @@  def run():
         # change the status code and move on.
         except IOError:
             status = -1
+
+    _silencestdio()
     sys.exit(status & 255)
 
 if pycompat.ispy3:
     def _initstdio():
         pass
+
+    def _silencestdio():
+        for fp in (sys.stdout, sys.stderr):
+            # Check if the file is okay
+            try:
+                fp.flush()
+                continue
+            except IOError:
+                pass
+            # Otherwise mark it as closed to silence "Exception ignored in"
+            # message emitted by the interpreter finalizer. Be careful to
+            # not close util.stdout, which may be a fdopen-ed file object and
+            # its close() actually closes the underlying file descriptor.
+            try:
+                fp.close()
+            except IOError:
+                pass
 else:
     def _initstdio():
         for fp in (sys.stdin, sys.stdout, sys.stderr):
             util.setbinary(fp)
 
+    def _silencestdio():
+        pass
+
 def _getsimilar(symbols, value):
     sim = lambda x: difflib.SequenceMatcher(None, value, x).ratio()
     # The cutoff for similarity here is pretty arbitrary. It should