[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_ <<