Patchwork D9152: hook: ignore EPIPE when flushing stdout/stderr

login
register
mail settings
Submitter phabricator
Date Oct. 5, 2020, 10:37 p.m.
Message ID <differential-rev-PHID-DREV-ctjrvhnxo4jr577mudtr-req@mercurial-scm.org>
Download mbox | patch
Permalink /patch/47381/
State Superseded
Headers show

Comments

phabricator - Oct. 5, 2020, 10:37 p.m.
mplamann created this revision.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REVISION SUMMARY
  This fixes the bug described in the parent commit.
  test-transaction-rollback-on-sigpipe.t is updated to show the new
  behavior.

REPOSITORY
  rHG Mercurial

BRANCH
  stable

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

AFFECTED FILES
  mercurial/hook.py
  tests/test-transaction-rollback-on-sigpipe.t

CHANGE DETAILS




To: mplamann, #hg-reviewers
Cc: mercurial-patches, mercurial-devel

Patch

diff --git a/tests/test-transaction-rollback-on-sigpipe.t b/tests/test-transaction-rollback-on-sigpipe.t
--- a/tests/test-transaction-rollback-on-sigpipe.t
+++ b/tests/test-transaction-rollback-on-sigpipe.t
@@ -66,4 +66,4 @@ 
   abort: stream ended unexpectedly (got 0 bytes, expected 4)
 
   $ check_for_abandoned_transaction
-  Abandoned transaction!
+  [1]
diff --git a/mercurial/hook.py b/mercurial/hook.py
--- a/mercurial/hook.py
+++ b/mercurial/hook.py
@@ -8,6 +8,7 @@ 
 from __future__ import absolute_import
 
 import contextlib
+import errno
 import os
 import sys
 
@@ -263,7 +264,6 @@ 
         r = res[hname][0] or r
     return r
 
-
 @contextlib.contextmanager
 def redirect_stdio():
     """Redirects stdout to stderr, if possible."""
@@ -289,10 +289,18 @@ 
         # The stderr is fully buffered on Windows when connected to a pipe.
         # A forcible flush is required to make small stderr data in the
         # remote side available to the client immediately.
-        procutil.stderr.flush()
+        try:
+            procutil.stderr.flush()
+        except IOError as err:
+            if err.errno not in (errno.EPIPE, errno.EIO, errno.EBADF):
+                raise error.StdioError(err)
 
         if _redirect and oldstdout >= 0:
-            procutil.stdout.flush()  # write hook output to stderr fd
+            try:
+                procutil.stdout.flush()  # write hook output to stderr fd
+            except IOError as err:
+                if err.errno not in (errno.EPIPE, errno.EIO, errno.EBADF):
+                    raise error.StdioError(err)
             os.dup2(oldstdout, stdoutno)
             os.close(oldstdout)