From fd7dcae8aa8c86008b3e1797808d39fb86c33ba7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Saugat=20Pachhai=20=28=E0=A4=B8=E0=A5=8C=E0=A4=97=E0=A4=BE?= =?UTF-8?q?=E0=A4=A4=29?= Date: Mon, 25 Jul 2022 16:02:12 +0545 Subject: [PATCH] cli/log: handle SIGPIPE errors `dvc | head` for example could fail with SIGPIPE and would print a traceback with BrokenPipeError exception. Now we redirect do /dev/null in case of error as suggested in Python's docs: https://docs.python.org/3/library/signal.html\#note-on-sigpipe. --- dvc/cli/__init__.py | 9 +++++++++ dvc/logger.py | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/dvc/cli/__init__.py b/dvc/cli/__init__.py index 590f956ef..e206befd6 100644 --- a/dvc/cli/__init__.py +++ b/dvc/cli/__init__.py @@ -189,6 +189,15 @@ def main(argv=None): # noqa: C901 except KeyboardInterrupt: logger.exception("interrupted by the user") ret = 252 + except BrokenPipeError: + import os + + # Python flushes standard streams on exit; redirect remaining output + # to devnull to avoid another BrokenPipeError at shutdown + # See: https://docs.python.org/3/library/signal.html#note-on-sigpipe + devnull = os.open(os.devnull, os.O_WRONLY) + os.dup2(devnull, sys.stdout.fileno()) + ret = 141 # 128 + 13 (SIGPIPE) except NotDvcRepoError: logger.exception("") ret = 253 diff --git a/dvc/logger.py b/dvc/logger.py index d44ca0835..cf3cce2a1 100644 --- a/dvc/logger.py +++ b/dvc/logger.py @@ -163,7 +163,7 @@ class LoggerHandler(logging.StreamHandler): msg, file=self.stream, end=getattr(self, "terminator", "\n") ) self.flush() - except RecursionError: + except (BrokenPipeError, RecursionError): raise except Exception: # noqa, pylint: disable=broad-except self.handleError(record)