diff options
Diffstat (limited to 'include/grpc++/impl/codegen/method_handler_impl.h')
-rw-r--r-- | include/grpc++/impl/codegen/method_handler_impl.h | 37 |
1 files changed, 33 insertions, 4 deletions
diff --git a/include/grpc++/impl/codegen/method_handler_impl.h b/include/grpc++/impl/codegen/method_handler_impl.h index c0af4ca130..daf090f86c 100644 --- a/include/grpc++/impl/codegen/method_handler_impl.h +++ b/include/grpc++/impl/codegen/method_handler_impl.h @@ -27,6 +27,27 @@ namespace grpc { namespace internal { + +// Invoke the method handler, fill in the status, and +// return whether or not we finished safely (without an exception). +// Note that exception handling is 0-cost in most compiler/library +// implementations (except when an exception is actually thrown), +// so this process doesn't require additional overhead in the common case. +// Additionally, we don't need to return if we caught an exception or not; +// the handling is the same in either case. +template <class Callable> +Status CatchingFunctionHandler(Callable&& handler) { +#if GRPC_ALLOW_EXCEPTIONS + try { + return handler(); + } catch (...) { + return Status(StatusCode::UNKNOWN, "Unexpected error in RPC handling"); + } +#else // GRPC_ALLOW_EXCEPTIONS + return handler(); +#endif // GRPC_ALLOW_EXCEPTIONS +} + /// A wrapper class of an application provided rpc method handler. template <class ServiceType, class RequestType, class ResponseType> class RpcMethodHandler : public MethodHandler { @@ -43,7 +64,9 @@ class RpcMethodHandler : public MethodHandler { param.request.bbuf_ptr(), &req); ResponseType rsp; if (status.ok()) { - status = func_(service_, param.server_context, &req, &rsp); + status = CatchingFunctionHandler([this, ¶m, &req, &rsp] { + return func_(service_, param.server_context, &req, &rsp); + }); } GPR_CODEGEN_ASSERT(!param.server_context->sent_initial_metadata_); @@ -86,7 +109,9 @@ class ClientStreamingHandler : public MethodHandler { void RunHandler(const HandlerParameter& param) final { ServerReader<RequestType> reader(param.call, param.server_context); ResponseType rsp; - Status status = func_(service_, param.server_context, &reader, &rsp); + Status status = CatchingFunctionHandler([this, ¶m, &reader, &rsp] { + return func_(service_, param.server_context, &reader, &rsp); + }); GPR_CODEGEN_ASSERT(!param.server_context->sent_initial_metadata_); CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage, @@ -130,7 +155,9 @@ class ServerStreamingHandler : public MethodHandler { if (status.ok()) { ServerWriter<ResponseType> writer(param.call, param.server_context); - status = func_(service_, param.server_context, &req, &writer); + status = CatchingFunctionHandler([this, ¶m, &req, &writer] { + return func_(service_, param.server_context, &req, &writer); + }); } CallOpSet<CallOpSendInitialMetadata, CallOpServerSendStatus> ops; @@ -172,7 +199,9 @@ class TemplatedBidiStreamingHandler : public MethodHandler { void RunHandler(const HandlerParameter& param) final { Streamer stream(param.call, param.server_context); - Status status = func_(param.server_context, &stream); + Status status = CatchingFunctionHandler([this, ¶m, &stream] { + return func_(param.server_context, &stream); + }); CallOpSet<CallOpSendInitialMetadata, CallOpServerSendStatus> ops; if (!param.server_context->sent_initial_metadata_) { |