Catch unprintable application exception (#32208)

* Catch unprintable application exception

* fix sanity

* Remove some files

* Fix typo
pull/32225/head
Xuan Wang 2 years ago committed by GitHub
parent 05a75d2d8c
commit 843cf42d6a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 8
      src/python/grpcio/grpc/_server.py
  2. 27
      src/python/grpcio_tests/tests/unit/_invocation_defects_test.py
  3. 7
      src/python/grpcio_tests/tests/unit/framework/common/test_control.py

@ -499,8 +499,12 @@ def _call_behavior(
_abort(state, rpc_event.call, cygrpc.StatusCode.unknown, _abort(state, rpc_event.call, cygrpc.StatusCode.unknown,
b'RPC Aborted') b'RPC Aborted')
elif exception not in state.rpc_errors: elif exception not in state.rpc_errors:
details = 'Exception calling application: {}'.format( try:
exception) details = 'Exception calling application: {}'.format(
exception)
except Exception: # pylint: disable=broad-except
details = 'Calling application raised unprintable Exception!'
traceback.print_exc()
_LOGGER.exception(details) _LOGGER.exception(details)
_abort(state, rpc_event.call, cygrpc.StatusCode.unknown, _abort(state, rpc_event.call, cygrpc.StatusCode.unknown,
_common.encode(details)) _common.encode(details))

@ -27,6 +27,7 @@ _SERIALIZE_RESPONSE = lambda bytestring: bytestring * 3
_DESERIALIZE_RESPONSE = lambda bytestring: bytestring[:len(bytestring) // 3] _DESERIALIZE_RESPONSE = lambda bytestring: bytestring[:len(bytestring) // 3]
_UNARY_UNARY = '/test/UnaryUnary' _UNARY_UNARY = '/test/UnaryUnary'
_UNARY_UNARY_NESTED_EXCEPTION = '/test/UnaryUnaryNestedException'
_UNARY_STREAM = '/test/UnaryStream' _UNARY_STREAM = '/test/UnaryStream'
_STREAM_UNARY = '/test/StreamUnary' _STREAM_UNARY = '/test/StreamUnary'
_STREAM_STREAM = '/test/StreamStream' _STREAM_STREAM = '/test/StreamStream'
@ -47,6 +48,10 @@ class _Handler(object):
),)) ),))
return request return request
def handle_unary_unary_with_nested_exception(self, request,
servicer_context):
raise test_control.NestedDefect()
def handle_unary_stream(self, request, servicer_context): def handle_unary_stream(self, request, servicer_context):
for _ in range(test_constants.STREAM_LENGTH): for _ in range(test_constants.STREAM_LENGTH):
self._control.control() self._control.control()
@ -128,6 +133,11 @@ class _GenericHandler(grpc.GenericRpcHandler):
self._handler.handle_stream_stream) self._handler.handle_stream_stream)
elif handler_call_details.method == _DEFECTIVE_GENERIC_RPC_HANDLER: elif handler_call_details.method == _DEFECTIVE_GENERIC_RPC_HANDLER:
return self._handler.defective_generic_rpc_handler() return self._handler.defective_generic_rpc_handler()
elif handler_call_details.method == _UNARY_UNARY_NESTED_EXCEPTION:
return _MethodHandler(
False, False, None, None,
self._handler.handle_unary_unary_with_nested_exception, None,
None, None)
else: else:
return None return None
@ -176,6 +186,10 @@ def _defective_handler_multi_callable(channel):
return channel.unary_unary(_DEFECTIVE_GENERIC_RPC_HANDLER) return channel.unary_unary(_DEFECTIVE_GENERIC_RPC_HANDLER)
def _defective_nested_exception_handler_multi_callable(channel):
return channel.unary_unary(_UNARY_UNARY_NESTED_EXCEPTION)
class InvocationDefectsTest(unittest.TestCase): class InvocationDefectsTest(unittest.TestCase):
"""Tests the handling of exception-raising user code on the client-side.""" """Tests the handling of exception-raising user code on the client-side."""
@ -260,6 +274,19 @@ class InvocationDefectsTest(unittest.TestCase):
self.assertIs(grpc.StatusCode.UNKNOWN, self.assertIs(grpc.StatusCode.UNKNOWN,
exception_context.exception.code()) exception_context.exception.code())
def testNestedExceptionGenericRpcHandlerUnaryResponse(self):
request = b'\x07\x08'
multi_callable = _defective_nested_exception_handler_multi_callable(
self._channel)
with self.assertRaises(grpc.RpcError) as exception_context:
multi_callable(request,
metadata=(('test',
'DefectiveGenericRpcHandlerUnary'),))
self.assertIs(grpc.StatusCode.UNKNOWN,
exception_context.exception.code())
if __name__ == '__main__': if __name__ == '__main__':
logging.basicConfig() logging.basicConfig()

@ -26,6 +26,13 @@ class Defect(Exception):
""" """
class NestedDefect(Exception):
"""Simulates a nested programming defect raised into in a system under test."""
def __str__(self):
raise Exception('Nested Exception')
class Control(abc.ABC): class Control(abc.ABC):
"""An object that accepts program control from a system under test. """An object that accepts program control from a system under test.

Loading…
Cancel
Save