Correct flaws in arc_summary[23] and their test.

The change correctly handles BrokenPipeError and improves the
associated tests.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Reviewed-by: John Kennedy <john.kennedy@delphix.com>
Signed-off-by: Rich Ercolani <rincebrain@gmail.com>
Closes #12037
Closes #12036
This commit is contained in:
Rich Ercolani 2021-05-25 22:02:01 -04:00 committed by GitHub
parent 211cee4fcf
commit f172c3088f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 73 additions and 51 deletions

View File

@ -102,18 +102,6 @@ show_tunable_descriptions = False
alternate_tunable_layout = False alternate_tunable_layout = False
def handle_Exception(ex_cls, ex, tb):
if ex is IOError:
if ex.errno == errno.EPIPE:
sys.exit()
if ex is KeyboardInterrupt:
sys.exit()
sys.excepthook = handle_Exception
def get_Kstat(): def get_Kstat():
"""Collect information on the ZFS subsystem from the /proc virtual """Collect information on the ZFS subsystem from the /proc virtual
file system. The name "kstat" is a holdover from the Solaris utility file system. The name "kstat" is a holdover from the Solaris utility
@ -1137,48 +1125,55 @@ def main():
global alternate_tunable_layout global alternate_tunable_layout
try: try:
opts, args = getopt.getopt(
sys.argv[1:],
"adp:h", ["alternate", "description", "page=", "help"]
)
except getopt.error as e:
sys.stderr.write("Error: %s\n" % e.msg)
usage()
sys.exit(1)
args = {}
for opt, arg in opts:
if opt in ('-a', '--alternate'):
args['a'] = True
if opt in ('-d', '--description'):
args['d'] = True
if opt in ('-p', '--page'):
args['p'] = arg
if opt in ('-h', '--help'):
usage()
sys.exit(0)
Kstat = get_Kstat()
alternate_tunable_layout = 'a' in args
show_tunable_descriptions = 'd' in args
pages = []
if 'p' in args:
try: try:
pages.append(unSub[int(args['p']) - 1]) opts, args = getopt.getopt(
except IndexError: sys.argv[1:],
sys.stderr.write('the argument to -p must be between 1 and ' + "adp:h", ["alternate", "description", "page=", "help"]
str(len(unSub)) + '\n') )
except getopt.error as e:
sys.stderr.write("Error: %s\n" % e.msg)
usage()
sys.exit(1) sys.exit(1)
else:
pages = unSub
zfs_header() args = {}
for page in pages: for opt, arg in opts:
page(Kstat) if opt in ('-a', '--alternate'):
sys.stdout.write("\n") args['a'] = True
if opt in ('-d', '--description'):
args['d'] = True
if opt in ('-p', '--page'):
args['p'] = arg
if opt in ('-h', '--help'):
usage()
sys.exit(0)
Kstat = get_Kstat()
alternate_tunable_layout = 'a' in args
show_tunable_descriptions = 'd' in args
pages = []
if 'p' in args:
try:
pages.append(unSub[int(args['p']) - 1])
except IndexError:
sys.stderr.write('the argument to -p must be between 1 and ' +
str(len(unSub)) + '\n')
sys.exit(1)
else:
pages = unSub
zfs_header()
for page in pages:
page(Kstat)
sys.stdout.write("\n")
except IOError as ex:
if (ex.errno == errno.EPIPE):
sys.exit(0)
raise
except KeyboardInterrupt:
sys.exit(0)
if __name__ == '__main__': if __name__ == '__main__':

View File

@ -43,6 +43,12 @@ import subprocess
import sys import sys
import time import time
# We can't use env -S portably, and we need python3 -u to handle pipes in
# the shell abruptly closing the way we want to, so...
import io
if isinstance(sys.__stderr__.buffer, io.BufferedWriter):
os.execv(sys.executable, [sys.executable, "-u"] + sys.argv)
DESCRIPTION = 'Print ARC and other statistics for OpenZFS' DESCRIPTION = 'Print ARC and other statistics for OpenZFS'
INDENT = ' '*8 INDENT = ' '*8
LINE_LENGTH = 72 LINE_LENGTH = 72
@ -221,6 +227,24 @@ elif sys.platform.startswith('linux'):
return descs return descs
def handle_unraisableException(exc_type, exc_value=None, exc_traceback=None,
err_msg=None, object=None):
handle_Exception(exc_type, object, exc_traceback)
def handle_Exception(ex_cls, ex, tb):
if ex_cls is KeyboardInterrupt:
sys.exit()
if ex_cls is BrokenPipeError:
# It turns out that while sys.exit() triggers an exception
# not handled message on Python 3.8+, os._exit() does not.
os._exit(0)
raise ex
if hasattr(sys,'unraisablehook'): # Python 3.8+
sys.unraisablehook = handle_unraisableException
sys.excepthook = handle_Exception
def cleanup_line(single_line): def cleanup_line(single_line):
"""Format a raw line of data from /proc and isolate the name value """Format a raw line of data from /proc and isolate the name value

View File

@ -48,6 +48,9 @@ else
set -A args "" "-a" "-d" "-p 1" set -A args "" "-a" "-d" "-p 1"
fi fi
# Without this, the below checks aren't going to work the way we hope...
set -o pipefail
typeset -i i=0 typeset -i i=0
while [[ $i -lt ${#args[*]} ]]; do while [[ $i -lt ${#args[*]} ]]; do
log_must eval "arc_summary ${args[i]} > /dev/null" log_must eval "arc_summary ${args[i]} > /dev/null"