|  | @@ -42,6 +42,8 @@ cdef class RPCState:
 | 
	
		
			
				|  |  |          self.abort_exception = None
 | 
	
		
			
				|  |  |          self.metadata_sent = False
 | 
	
		
			
				|  |  |          self.status_sent = False
 | 
	
		
			
				|  |  | +        self.status_code = StatusCode.ok
 | 
	
		
			
				|  |  | +        self.status_details = ''
 | 
	
		
			
				|  |  |          self.trailing_metadata = _IMMUTABLE_EMPTY_METADATA
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      cdef bytes method(self):
 | 
	
	
		
			
				|  | @@ -143,6 +145,9 @@ cdef class _ServicerContext:
 | 
	
		
			
				|  |  |              if trailing_metadata == _IMMUTABLE_EMPTY_METADATA and self._rpc_state.trailing_metadata:
 | 
	
		
			
				|  |  |                  trailing_metadata = self._rpc_state.trailing_metadata
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +            if details == '' and self._rpc_state.status_details:
 | 
	
		
			
				|  |  | +                details = self._rpc_state.status_details
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |              actual_code = get_status_code(code)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |              self._rpc_state.status_sent = True
 | 
	
	
		
			
				|  | @@ -163,6 +168,12 @@ cdef class _ServicerContext:
 | 
	
		
			
				|  |  |      def invocation_metadata(self):
 | 
	
		
			
				|  |  |          return self._rpc_state.invocation_metadata()
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +    def set_code(self, object code):
 | 
	
		
			
				|  |  | +        self._rpc_state.status_code = get_status_code(code)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    def set_details(self, str details):
 | 
	
		
			
				|  |  | +        self._rpc_state.status_details = details
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  cdef _find_method_handler(str method, tuple metadata, list generic_handlers):
 | 
	
		
			
				|  |  |      cdef _HandlerCallDetails handler_call_details = _HandlerCallDetails(method,
 | 
	
	
		
			
				|  | @@ -209,8 +220,8 @@ async def _finish_handler_with_unary_response(RPCState rpc_state,
 | 
	
		
			
				|  |  |          SendMessageOperation(response_raw, _EMPTY_FLAGS),
 | 
	
		
			
				|  |  |          SendStatusFromServerOperation(
 | 
	
		
			
				|  |  |              rpc_state.trailing_metadata,
 | 
	
		
			
				|  |  | -            StatusCode.ok,
 | 
	
		
			
				|  |  | -            b'',
 | 
	
		
			
				|  |  | +            rpc_state.status_code,
 | 
	
		
			
				|  |  | +            rpc_state.status_details,
 | 
	
		
			
				|  |  |              _EMPTY_FLAGS,
 | 
	
		
			
				|  |  |          ),
 | 
	
		
			
				|  |  |      )
 | 
	
	
		
			
				|  | @@ -262,8 +273,8 @@ async def _finish_handler_with_stream_responses(RPCState rpc_state,
 | 
	
		
			
				|  |  |      # Sends the final status of this RPC
 | 
	
		
			
				|  |  |      cdef SendStatusFromServerOperation op = SendStatusFromServerOperation(
 | 
	
		
			
				|  |  |          rpc_state.trailing_metadata,
 | 
	
		
			
				|  |  | -        StatusCode.ok,
 | 
	
		
			
				|  |  | -        b'',
 | 
	
		
			
				|  |  | +        rpc_state.status_code,
 | 
	
		
			
				|  |  | +        rpc_state.status_details,
 | 
	
		
			
				|  |  |          _EMPTY_FLAGS,
 | 
	
		
			
				|  |  |      )
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -419,11 +430,20 @@ async def _handle_exceptions(RPCState rpc_state, object rpc_coro, object loop):
 | 
	
		
			
				|  |  |      except _ServerStoppedError:
 | 
	
		
			
				|  |  |          _LOGGER.info('Aborting RPC due to server stop.')
 | 
	
		
			
				|  |  |      except Exception as e:
 | 
	
		
			
				|  |  | -        _LOGGER.exception(e)
 | 
	
		
			
				|  |  | +        _LOGGER.exception('Unexpected [%s] raised by servicer method [%s]' % (
 | 
	
		
			
				|  |  | +            type(e).__name__,
 | 
	
		
			
				|  |  | +            _decode(rpc_state.method()),
 | 
	
		
			
				|  |  | +        ))
 | 
	
		
			
				|  |  |          if not rpc_state.status_sent and rpc_state.server._status != AIO_SERVER_STATUS_STOPPED:
 | 
	
		
			
				|  |  | +            # Allows users to raise other types of exception with specified status code
 | 
	
		
			
				|  |  | +            if rpc_state.status_code == StatusCode.ok:
 | 
	
		
			
				|  |  | +                status_code = StatusCode.unknown
 | 
	
		
			
				|  |  | +            else:
 | 
	
		
			
				|  |  | +                status_code = rpc_state.status_code
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |              await _send_error_status_from_server(
 | 
	
		
			
				|  |  |                  rpc_state,
 | 
	
		
			
				|  |  | -                StatusCode.unknown,
 | 
	
		
			
				|  |  | +                status_code,
 | 
	
		
			
				|  |  |                  'Unexpected %s: %s' % (type(e), e),
 | 
	
		
			
				|  |  |                  rpc_state.trailing_metadata,
 | 
	
		
			
				|  |  |                  rpc_state.metadata_sent,
 |