stdio: raise StdioError if something goes wrong in ui.flush
authorBryan O'Sullivan <bryano@fb.com>
Tue, 11 Apr 2017 14:54:12 -0700
changeset 31963 1bfb9a63b98e
parent 31962 e9646ff34d55
child 31964 ebaada96aec3
stdio: raise StdioError if something goes wrong in ui.flush The prior code used to ignore all errors, which was intended to deal with a decade-old problem with writing to broken pipes on Windows. However, that code inadvertantly went a lot further, making it impossible to detect *all* I/O errors on stdio ... but only sometimes. What actually happened was that if Mercurial wrote less than a stdio buffer's worth of output (the overwhelmingly common case for most commands), any error that occurred would get swallowed here. But if the buffering strategy changed, an unhandled IOError could be raised from any number of other locations. Because we now have a top-level StdioError handler, and ui._write and ui._write_err (and now flush!) will raise that exception, we have one rational place to detect and handle these errors.
mercurial/ui.py
--- a/mercurial/ui.py	Tue Apr 11 14:54:12 2017 -0700
+++ b/mercurial/ui.py	Tue Apr 11 14:54:12 2017 -0700
@@ -807,10 +807,15 @@
         # opencode timeblockedsection because this is a critical path
         starttime = util.timer()
         try:
-            try: self.fout.flush()
-            except (IOError, ValueError): pass
-            try: self.ferr.flush()
-            except (IOError, ValueError): pass
+            try:
+                self.fout.flush()
+            except IOError as err:
+                raise error.StdioError(err)
+            finally:
+                try:
+                    self.ferr.flush()
+                except IOError as err:
+                    raise error.StdioError(err)
         finally:
             self._blockedtimes['stdio_blocked'] += \
                 (util.timer() - starttime) * 1000