python/semanage: empty stdout before exiting on BrokenPipeError

Empty stdout buffer before exiting when BrokenPipeError is
encountered. Otherwise python will flush the bufer during exit, which
may trigger the exception again.
https://docs.python.org/3/library/signal.html#note-on-sigpipe

Fixes:
   #semanage fcontext -l | egrep -q -e '^/home'
   BrokenPipeError: [Errno 32] Broken pipe
   Exception ignored in: <_io.TextIOWrapper name='<stdout>' mode='w' encoding='UTF-8'>
   BrokenPipeError: [Errno 32] Broken pipe

Note that the error above only appears occasionally (usually only the
first line is printed).

Signed-off-by: Vit Mojzis <vmojzis@redhat.com>
Acked-by: Nicolas Iooss <nicolas.iooss@m4x.org>
This commit is contained in:
Vit Mojzis 2021-01-05 17:00:21 +01:00 committed by Petr Lautrbach
parent 34bd9a9d19
commit 92e01969d0

View file

@ -27,6 +27,7 @@ import traceback
import argparse
import seobject
import sys
import os
PROGNAME = "policycoreutils"
try:
import gettext
@ -945,6 +946,13 @@ def do_parser():
args = commandParser.parse_args(make_args(sys.argv))
args.func(args)
sys.exit(0)
except BrokenPipeError as e:
sys.stderr.write("%s: %s\n" % (e.__class__.__name__, str(e)))
# Python flushes standard streams on exit; redirect remaining output
# to devnull to avoid another BrokenPipeError at shutdown
devnull = os.open(os.devnull, os.O_WRONLY)
os.dup2(devnull, sys.stdout.fileno())
sys.exit(1)
except IOError as e:
sys.stderr.write("%s: %s\n" % (e.__class__.__name__, str(e)))
sys.exit(1)