martinvonz created this revision.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REVISION SUMMARY
  When the pager dies, we get a `SIGPIPE`. That causes
  `error.SignalInterrupt` to be raised ` (from `ui._catchterm()`). Any
  further writes or flushes will cause further `SIGPIPE`s and furhter
  `error.SignalInterrupt`. If we write or flush outside of the
  try/except that handle `KeyboardInterrupt` (which
  `error.SignalInterrupt` is a subclass of), then control will escape
  from the `dispatch` module. Let's fix that by ignoring errors from
  flushing the ui.
  
  I would have rather fixed this by restoring the stdout and stderr
  streams when the pager dies, but it gets complicated because of
  multiple ui instances (ui/lui) and different pager setups between
  regular hg and chg.
  
  This changes a test in `test-pager.t`, but I don't understand why. I
  would have thought that all the output from the command should have
  gone to the broken pager.

REPOSITORY
  rHG Mercurial

BRANCH
  default

REVISION DETAIL
  https://phab.mercurial-scm.org/D11627

AFFECTED FILES
  mercurial/dispatch.py
  tests/test-pager.t

CHANGE DETAILS

diff --git a/tests/test-pager.t b/tests/test-pager.t
--- a/tests/test-pager.t
+++ b/tests/test-pager.t
@@ -219,8 +219,7 @@
 #endif
 
 A complicated pager command gets worse behavior. Bonus points if you can
-improve this. Windows apparently does this better, but only sometimes?
-#if windows
+improve this.
   $ hg log --limit 3 \
   >   --config pager.pager='this-command-better-never-exist --seriously' \
   >  2>/dev/null || true
@@ -240,11 +239,6 @@
   date:        Thu Jan 01 00:00:00 1970 +0000 (?)
   summary:     modify a 8 (?)
    (?)
-#else
-  $ hg log --limit 3 \
-  >   --config pager.pager='this-command-better-never-exist --seriously' \
-  >  2>/dev/null || true
-#endif
 
 Pager works with shell aliases.
 
diff --git a/mercurial/dispatch.py b/mercurial/dispatch.py
--- a/mercurial/dispatch.py
+++ b/mercurial/dispatch.py
@@ -252,9 +252,14 @@
         err = e
         status = -1
 
-    ret = _flushstdio(req.ui, err)
-    if ret and not status:
-        status = ret
+    # Somehow we have to catcht he exception here; catching it inside
+    # _flushstdio() doesn't work.
+    try:
+        ret = _flushstdio(req.ui, err)
+        if ret and not status:
+            status = ret
+    except BaseException:
+        pass
     return status
 
 
@@ -314,7 +319,10 @@
             ret = -1
         finally:
             duration = util.timer() - starttime
-            req.ui.flush()  # record blocked times
+            try:
+                req.ui.flush()  # record blocked times
+            except BaseException:
+                pass
             if req.ui.logblockedtimes:
                 req.ui._blockedtimes[b'command_duration'] = duration * 1000
                 req.ui.log(
@@ -338,7 +346,10 @@
             except:  # exiting, so no re-raises
                 ret = ret or -1
             # do flush again since ui.log() and exit handlers may write to ui
-            req.ui.flush()
+            try:
+                req.ui.flush()
+            except BaseException:
+                pass
         return ret
 
 
@@ -459,7 +470,10 @@
                 try:
                     return _dispatch(req)
                 finally:
-                    ui.flush()
+                    try:
+                        ui.flush()  # record blocked times
+                    except BaseException:
+                        pass
             except:  # re-raises
                 # enter the debugger when we hit an exception
                 if req.earlyoptions[b'debugger']:



To: martinvonz, #hg-reviewers
Cc: mercurial-patches, mercurial-devel
_______________________________________________
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel

Reply via email to