Re: [ros-users] Throwing exceptions in services (Python vs. …

Top Page
Attachments:
Message as email
+ (text/plain)
+ issue3590.patch (text/x-patch)
Delete this message
Reply to this message
Author: User discussions
Date:  
To: User discussions
Subject: Re: [ros-users] Throwing exceptions in services (Python vs. C++)
I have created and attached a patch for issue https://code.ros.org/trac/ros/ticket/3590

It currently does the following:
- for every std::exception already catched on the server it passes the e.what() to the client (as rospy and roslisp already do)
- output an error message on the client containing the exception string in case of server-side exceptions

One open question is if a new exception should be introduced (ServiceException similar to rospy)?

Then only error messages from ServiceException would be passed from server to client (other exceptions are handled without passing the error message).
And on the client the same exception-type could be (re-)thrown.
While this approach looks much cleaner it work break with the current behavior.

What is your opinion on the patch?
Would you vote to modify the patch to introduce a ServiceException as described above?

Dirk
Index: clients/cpp/roscpp_serialization/include/ros/serialization.h
===================================================================
--- clients/cpp/roscpp_serialization/include/ros/serialization.h    (revision 15393)
+++ clients/cpp/roscpp_serialization/include/ros/serialization.h    (working copy)
@@ -835,11 +835,13 @@
   }
   else
   {
-    m.num_bytes = 5;
-    m.buf.reset(new uint8_t[5]);
+    uint32_t len = serializationLength(message);
+    m.num_bytes = len + 1;
+    m.buf.reset(new uint8_t[m.num_bytes]);
+
     OStream s(m.buf.get(), (uint32_t)m.num_bytes);
     serialize(s, (uint8_t)ok);
-    serialize(s, (uint32_t)0);
+    serialize(s, message);
   }


   return m;
Index: clients/cpp/roscpp/include/ros/service_server_link.h
===================================================================
--- clients/cpp/roscpp/include/ros/service_server_link.h    (revision 15393)
+++ clients/cpp/roscpp/include/ros/service_server_link.h    (working copy)
@@ -70,6 +70,8 @@


     bool success_;
     bool call_finished_;
+
+    std::string exception_string_;
   };
   typedef boost::shared_ptr<CallInfo> CallInfoPtr;
   typedef std::queue<CallInfoPtr> Q_CallInfo;
Index: clients/cpp/roscpp/src/libros/service_publication.cpp
===================================================================
--- clients/cpp/roscpp/src/libros/service_publication.cpp    (revision 15393)
+++ clients/cpp/roscpp/src/libros/service_publication.cpp    (working copy)
@@ -39,6 +39,8 @@


#include <boost/bind.hpp>

+#include <std_msgs/String.h>
+
namespace ros
{

@@ -126,7 +128,9 @@
     catch (std::exception& e)
     {
       ROS_ERROR("Exception thrown while processing service call: %s", e.what());
-      SerializedMessage res = serialization::serializeServiceResponse(false, 0);
+      std_msgs::String error_string;
+      error_string.data = e.what();
+      SerializedMessage res = serialization::serializeServiceResponse(false, error_string);
       link_->processResponse(false, res);
       return Invalid;
     }
Index: clients/cpp/roscpp/src/libros/service_server_link.cpp
===================================================================
--- clients/cpp/roscpp/src/libros/service_server_link.cpp    (revision 15393)
+++ clients/cpp/roscpp/src/libros/service_server_link.cpp    (working copy)
@@ -236,6 +236,10 @@
     {
       *current_call_->resp_ = SerializedMessage(buffer, size);
     }
+    else
+    {
+      current_call_->exception_string_ = std::string(reinterpret_cast<char*>(buffer.get()), size);
+    }
   }


callFinished();
@@ -363,6 +367,11 @@

info->call_finished_ = true;

+  if (info->exception_string_.length() > 0)
+  {
+    ROS_ERROR("Service call failed: service [%s] responded with an error: %s", service_name_.c_str(), info->exception_string_.c_str());
+  }
+
   return info->success_;
 }