12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182 |
- # Copyright 2020 The Chromium Authors. All rights reserved.
- # Use of this source code is governed by a BSD-style license that can be
- # found in the LICENSE file.
- """Converts exceptions to return codes and prints error messages.
- This makes it easier to query build tables for particular error types as
- exit codes are visible to queries while exception stack traces are not."""
- import errno
- import fcntl
- import logging
- import os
- import subprocess
- import sys
- import traceback
- from device_target import ProvisionDeviceException
- from target import FuchsiaTargetException
- def _PrintException(value, trace):
- """Prints stack trace and error message for the current exception."""
- traceback.print_tb(trace)
- print(str(value))
- def IsStdoutBlocking():
- """Returns True if sys.stdout is blocking or False if non-blocking.
- sys.stdout should always be blocking. Non-blocking is associated with
- intermittent IOErrors (crbug.com/1080858).
- """
- nonblocking = fcntl.fcntl(sys.stdout, fcntl.F_GETFL) & os.O_NONBLOCK
- return not nonblocking
- def HandleExceptionAndReturnExitCode():
- """Maps the current exception to a return code and prints error messages.
- Mapped exception types are assigned blocks of 8 return codes starting at 64.
- The choice of 64 as the starting code is based on the Advanced Bash-Scripting
- Guide (http://tldp.org/LDP/abs/html/exitcodes.html).
- A generic exception is mapped to the start of the block. More specific
- exceptions are mapped to numbers inside the block. For example, a
- FuchsiaTargetException is mapped to return code 64, unless it involves SSH
- in which case it is mapped to return code 65.
- Exceptions not specifically mapped go to return code 1.
- Returns the mapped return code."""
- (type, value, trace) = sys.exc_info()
- _PrintException(value, trace)
- if type is FuchsiaTargetException:
- if 'ssh' in str(value).lower():
- print('Error: FuchsiaTargetException: SSH to Fuchsia target failed.')
- return 65
- return 64
- elif type is IOError:
- if value.errno == errno.EAGAIN:
- logging.info('Python print to sys.stdout probably failed')
- if not IsStdoutBlocking():
- logging.warn('sys.stdout is non-blocking')
- return 73
- return 72
- elif type is subprocess.CalledProcessError:
- if os.path.basename(value.cmd[0]) == 'scp':
- print('Error: scp operation failed - %s' % str(value))
- return 81
- if os.path.basename(value.cmd[0]) == 'qemu-img':
- print('Error: qemu-img fuchsia image generation failed.')
- return 82
- return 80
- elif type is ProvisionDeviceException:
- print('Error: Failed to pave device')
- return 90
- else:
- return 1
|