Wraps DBus / efl interactions in try / catch blocks 06/167606/2
authorRadoslaw Cybulski <r.cybulski@partner.samsung.com>
Thu, 18 Jan 2018 13:58:46 +0000 (14:58 +0100)
committerRadoslaw Cybulski <r.cybulski@partner.samsung.com>
Mon, 22 Jan 2018 19:02:46 +0000 (20:02 +0100)
Adds try / catch statements around calls, which might leak exceptions
to efl, which doesn't support it (efl is written in C).
Exceptions will be changed to error states with message.

Change-Id: I8ff483b14d9df39b179874896aba9f93ec2df103

src/DBus.hpp
src/batch/EvaluationValue.hpp

index be7b9b9..52ab3da 100644 (file)
@@ -2171,7 +2171,13 @@ namespace DBus
                                                DBUS_DEBUG("call %d: failed: %s", callId.id, params.getError().message.c_str());
                                                return;
                                        }
-                                       detail::apply(callback, params.getValues());
+                                       try
+                                       {
+                                               detail::apply(callback, params.getValues());
+                                       } catch (...)
+                                       {
+                                               ERROR("unhandled exception");
+                                       }
                                }
                        };
                        auto handler = eldbus_proxy_signal_handler_add(connectionState.proxy, signalName.c_str(), listenerCallback, tmp);
@@ -2331,15 +2337,23 @@ namespace DBus
                                z.getCallback = [ = ](const Eldbus_Message * src, Eldbus_Message_Iter * dst) -> ValueOrError<void> {
                                        detail::emitNotification(eldbus_message_sender_get(src),
                                                                                         eldbus_message_path_get(src), interfaceName.c_str(), memberName.c_str(), DBusActionType::GETTER_RESPONSE);
-                                       auto v = detail::apply(getter, std::tuple<>{});
-                                       if (v)
+                                       try
+                                       {
+                                               auto v = detail::apply(getter, std::tuple<> {});
+                                               if (v) {
+                                                       detail::signature<T>::set(dst, std::get<0>(v.getValues()));
+                                                       DBUS_DEBUG("call %d: success", getterId.id);
+                                                       return Success{};
+                                               }
+                                               DBUS_DEBUG("call %d: failed: %s", getterId.id, v.getError().message.c_str());
+                                               return v.getError();
+                                       } catch (std::exception &e)
                                        {
-                                               detail::signature<T>::set(dst, std::get<0>(v.getValues()));
-                                               DBUS_DEBUG("call %d: success", getterId.id);
-                                               return Success{};
+                                               return Error{ std::string("unhandled exception (") + e.what() + ")" };
+                                       } catch (...)
+                                       {
+                                               return Error{ "unhandled exception" };
                                        }
-                                       DBUS_DEBUG("call %d: failed: %s", getterId.id, v.getError().message.c_str());
-                                       return v.getError();
                                };
                        }
                        if (setter) {
@@ -2353,14 +2367,20 @@ namespace DBus
                                        auto src_signature = eldbus_message_iter_signature_get(src_iter);
                                        if (detail::signature<T>::get(src_iter, std::get<0>(value)))
                                        {
-                                               auto v = detail::apply(setter, std::move(value));
-                                               if (v) {
-                                                       DBUS_DEBUG("call %d: success", setterId.id);
-                                                       return Success{};
+                                               try {
+                                                       auto v = detail::apply(setter, std::move(value));
+                                                       if (v) {
+                                                               DBUS_DEBUG("call %d: success", setterId.id);
+                                                               return Success{};
+                                                       }
+                                                       DBUS_DEBUG("call %d: failed: %s", setterId.id, v.getError().message.c_str());
+                                                       free(src_signature);
+                                                       return v.getError();
+                                               } catch (std::exception &e) {
+                                                       return Error{ std::string("unhandled exception (") + e.what() + ")" };
+                                               } catch (...) {
+                                                       return Error{ "unhandled exception" };
                                                }
-                                               DBUS_DEBUG("call %d: failed: %s", setterId.id, v.getError().message.c_str());
-                                               free(src_signature);
-                                               return v.getError();
                                        }
                                        DBUS_DEBUG("call %d: failed to unpack values, got signature '%s', expected '%s'", setterId.id,
                                                           src_signature, detail::signature<T>::sig().c_str());
@@ -2409,14 +2429,23 @@ namespace DBus
                                auto args = detail::unpackValues<VEArgs>(callId, msg);
                                if (args)
                                {
-                                       auto v = detail::apply(callback, std::move(args.getValues()));
-                                       if (v) {
-                                               DBUS_DEBUG("call %d: success", callId.id);
-                                               ret = eldbus_message_method_return_new(msg);
-                                               packValues(callId, ret, v);
-                                       } else {
-                                               DBUS_DEBUG("call %d: failed: %s", callId.id, v.getError().message.c_str());
-                                               ret = eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.Failed", v.getError().message.c_str());
+                                       auto error = [&](const std::string & txt) {
+                                               DBUS_DEBUG("call %d: failed: %s", callId.id, txt.c_str());
+                                               ret = eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.Failed", txt.c_str());
+                                       };
+                                       try {
+                                               auto v = detail::apply(callback, std::move(args.getValues()));
+                                               if (v) {
+                                                       DBUS_DEBUG("call %d: success", callId.id);
+                                                       ret = eldbus_message_method_return_new(msg);
+                                                       packValues(callId, ret, v);
+                                               } else {
+                                                       error(v.getError().message);
+                                               }
+                                       } catch (std::exception &e) {
+                                               error(std::string("unhandled exception (") + e.what() + ")");
+                                       } catch (...) {
+                                               error("unhandled exception");
                                        }
                                } else
                                {
@@ -2590,9 +2619,7 @@ namespace DBus
                        auto connection = DBusServer::getCurrentConnection();
                        auto retCallback = [ = ](typename detail::dbus_interface_traits<T>::Ret v)
                        {
-                               DBUS_DEBUG(".");
                                if (v) {
-                                       DBUS_DEBUG(".");
                                        callState->reply = eldbus_message_method_return_new(callState->message.get());
                                        packValues(callId, callState->reply, v);
                                } else {
@@ -2600,7 +2627,6 @@ namespace DBus
                                        callState->reply = eldbus_message_error_new(callState->message.get(), "org.freedesktop.DBus.Error.Failed", v.getError().message.c_str());
                                }
                                if (!callState->replyRunning) {
-                                       DBUS_DEBUG(".");
                                        eldbus_connection_send(connection.get(), callState->reply, NULL, NULL, -1);
                                }
                        };
@@ -2608,7 +2634,20 @@ namespace DBus
                        auto args = detail::unpackValues<VEArgs>(callId, msg);
                        if (args)
                        {
-                               detail::apply(callback, std::move(retCallback), std::move(args.getValues()));
+                               auto error = [&](const std::string & txt) {
+                                       if (!callState->reply) {
+                                               DBUS_DEBUG("call %d: failed: %s", callId.id, txt.c_str());
+                                               callState->reply = eldbus_message_error_new(callState->message.get(), "org.freedesktop.DBus.Error.Failed", txt.c_str());
+                                       }
+                               };
+                               try {
+                                       detail::apply(callback, std::move(retCallback), std::move(args.getValues()));
+                               } catch (std::exception &e) {
+                                       error(std::string("unhandled exception (") + e.what() + ")");
+                               } catch (...) {
+                                       error("unhandled exception");
+                               }
+
                                callState->replyRunning = false;
                                ret = callState->reply;
                        } else
index e46406a..a9240ca 100644 (file)
@@ -35,7 +35,7 @@
 class EvaluationValue;
 class EvaluationContext;
 
-class EvaluationFailure
+class EvaluationFailure : public std::exception
 {
 public:
        EvaluationFailure() = default;
@@ -50,9 +50,15 @@ public:
                (*text) << std::forward<T>(t);
                return *this;
        }
+       const char *what() const noexcept
+       {
+               cachedText = text->str();
+               return cachedText.c_str();
+       }
 private:
        std::shared_ptr<std::ostringstream> text = std::make_shared<std::ostringstream>();
        Optional<TokenLocation> location_;
+       mutable std::string cachedText;
 };
 
 namespace detail