aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar Vijay Pai <vpai@google.com>2018-09-14 14:31:48 -0700
committerGravatar Vijay Pai <vpai@google.com>2018-09-14 16:56:19 -0700
commit73d89a66f90eb8cf5e9b8939690ebf7347fba147 (patch)
tree981d4116a945ee6cf2d81f44ca65a1ed5c87c05e /src
parentff449831884eedb2519b43008c6ee13caf4d1853 (diff)
Catch exceptions in user callbacks
Diffstat (limited to 'src')
-rw-r--r--src/cpp/common/callback_common.cc28
1 files changed, 23 insertions, 5 deletions
diff --git a/src/cpp/common/callback_common.cc b/src/cpp/common/callback_common.cc
index ae47901f1b..fa586286d1 100644
--- a/src/cpp/common/callback_common.cc
+++ b/src/cpp/common/callback_common.cc
@@ -26,8 +26,21 @@
namespace grpc {
namespace internal {
-
namespace {
+
+template <class Func, class Arg>
+void CatchingCallback(Func&& func, Arg&& arg) {
+#if GRPC_ALLOW_EXCEPTIONS
+ try {
+ func(arg);
+ } catch (...) {
+ // nothing to return or change here, just don't crash the library
+ }
+#else // GRPC_ALLOW_EXCEPTIONS
+ func(arg);
+#endif // GRPC_ALLOW_EXCEPTIONS
+}
+
class CallbackWithSuccessImpl : public grpc_core::CQCallbackInterface {
public:
static void operator delete(void* ptr, std::size_t size) {
@@ -52,8 +65,11 @@ class CallbackWithSuccessImpl : public grpc_core::CQCallbackInterface {
bool new_ok = ok;
GPR_ASSERT(parent_->ops()->FinalizeResult(&ignored, &new_ok));
GPR_ASSERT(ignored == parent_->ops());
- func_(ok);
- func_ = nullptr; // release the function
+
+ // Last use of func_ or ok, so ok to move them out for rvalue call above
+ CatchingCallback(std::move(func_), std::move(ok));
+
+ func_ = nullptr; // reset to clear this out for sure
grpc_call_unref(call_);
}
@@ -88,8 +104,10 @@ class CallbackWithStatusImpl : public grpc_core::CQCallbackInterface {
GPR_ASSERT(parent_->ops()->FinalizeResult(&ignored, &ok));
GPR_ASSERT(ignored == parent_->ops());
- func_(status_);
- func_ = nullptr; // release the function
+ // Last use of func_ or status_, so ok to move them out
+ CatchingCallback(std::move(func_), std::move(status_));
+
+ func_ = nullptr; // reset to clear this out for sure
grpc_call_unref(call_);
}
Status* status_ptr() { return &status_; }