[thrift] C++: Pass std::exception from server to client
Summary: Rather than an uncaught exception dropping the connection, catching std::exception (and anything derived from it) and passing its message payload back in the form of a T_EXCEPTION message is a much cleaner response.
Reviewed By: mcslee
Test Plan: compile generated code for Synapse's tablet interface, throw a generic exception at the server, observe the message for the exception arising from the client in the form of a TApplicationException (instead of the previous 'no more data to read' exception)
Revert: ok
git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@665264 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/compiler/cpp/src/generate/t_cpp_generator.cc b/compiler/cpp/src/generate/t_cpp_generator.cc
index 7a31bc6..a92be52 100644
--- a/compiler/cpp/src/generate/t_cpp_generator.cc
+++ b/compiler/cpp/src/generate/t_cpp_generator.cc
@@ -1799,11 +1799,9 @@
}
// Try block for functions with exceptions
- if (xceptions.size() > 0) {
- f_service_ <<
- indent() << "try {" << endl;
- indent_up();
- }
+ f_service_ <<
+ indent() << "try {" << endl;
+ indent_up();
// Generate the function call
t_struct* arg_struct = tfunction->get_arglist();
@@ -1839,9 +1837,10 @@
indent() << "result.__isset.success = true;" << endl;
}
- if (!tfunction->is_async() && xceptions.size() > 0) {
- indent_down();
- f_service_ << indent() << "}";
+ indent_down();
+ f_service_ << indent() << "}";
+
+ if (!tfunction->is_async()) {
for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
f_service_ << " catch (" << (*x_iter)->get_type()->get_name() << " &" << (*x_iter)->get_name() << ") {" << endl;
if (!tfunction->is_async()) {
@@ -1855,9 +1854,24 @@
f_service_ << "}";
}
}
- f_service_ << endl;
}
+ f_service_ << " catch (const std::exception& e) {" << endl;
+
+ if (!tfunction->is_async()) {
+ indent_up();
+ f_service_ <<
+ indent() << "facebook::thrift::TApplicationException x(e.what());" << endl <<
+ indent() << "oprot->writeMessageBegin(\"" << tfunction->get_name() << "\", facebook::thrift::protocol::T_EXCEPTION, seqid);" << endl <<
+ indent() << "x.write(oprot);" << endl <<
+ indent() << "oprot->writeMessageEnd();" << endl <<
+ indent() << "oprot->getTransport()->flush();" << endl <<
+ indent() << "oprot->getTransport()->writeEnd();" << endl <<
+ indent() << "return;" << endl;
+ indent_down();
+ }
+ f_service_ << indent() << "}" << endl;
+
// Shortcut out here for async functions
if (tfunction->is_async()) {
f_service_ <<