THRIFT-2860 Delphi server closes connection on unexpected exceptions
Client: Delphi
Patch: Jens Geyer
diff --git a/compiler/cpp/src/generate/t_delphi_generator.cc b/compiler/cpp/src/generate/t_delphi_generator.cc
index 682c18d..b7667b8 100644
--- a/compiler/cpp/src/generate/t_delphi_generator.cc
+++ b/compiler/cpp/src/generate/t_delphi_generator.cc
@@ -2351,6 +2351,7 @@
if (!tfunction->is_oneway()) {
indent_impl(s_service_impl) << "msg: Thrift.Protocol.IMessage;" << endl;
indent_impl(s_service_impl) << "ret: " << result_intfnm << ";" << endl;
+ indent_impl(s_service_impl) << "appx : TApplicationException;" << endl;
}
indent_down_impl();
@@ -2375,10 +2376,8 @@
indent_impl(s_service_impl) << "ret := " << result_clsnm << "Impl.Create;" << endl;
}
- if (events_ || (!tfunction->is_oneway() && xceptions.size() > 0)) {
- indent_impl(s_service_impl) << "try" << endl;
- indent_up_impl();
- }
+ indent_impl(s_service_impl) << "try" << endl;
+ indent_up_impl();
t_struct* arg_struct = tfunction->get_arglist();
const std::vector<t_field*>& fields = arg_struct->get_members();
@@ -2405,37 +2404,52 @@
<< " := " << empty_value((*f_iter)->get_type()) << ";" << endl;
}
- if (events_ || (!tfunction->is_oneway() && xceptions.size() > 0)) {
- indent_down_impl();
- indent_impl(s_service_impl) << "except" << endl;
+ indent_down_impl();
+ indent_impl(s_service_impl) << "except" << endl;
+ indent_up_impl();
+
+ for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
+ indent_impl(s_service_impl) << "on E: " << type_name((*x_iter)->get_type(), true, true)
+ << " do begin" << endl;
indent_up_impl();
- for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
- indent_impl(s_service_impl) << "on E: " << type_name((*x_iter)->get_type(), true, true)
- << " do" << endl;
- indent_impl(s_service_impl) << "begin" << endl;
- indent_up_impl();
- if (!tfunction->is_oneway()) {
- string factory_name = normalize_clsnm((*x_iter)->get_type()->get_name(), "", true)
- + "Factory";
- indent_impl(s_service_impl) << "ret." << prop_name(*x_iter) << " := E." << factory_name
- << ";" << endl;
- }
- indent_down_impl();
- indent_impl(s_service_impl) << "end;" << endl;
- }
- if (events_) {
- indent_impl(s_service_impl) << "on E: Exception do" << endl;
- indent_impl(s_service_impl) << "begin" << endl;
- indent_up_impl();
- indent_impl(s_service_impl) << "if events <> nil then events.UnhandledError(E);" << endl;
- indent_impl(s_service_impl) << "raise; // let it bubble up" << endl;
- indent_down_impl();
- indent_impl(s_service_impl) << "end;" << endl;
+ if (!tfunction->is_oneway()) {
+ string factory_name = normalize_clsnm((*x_iter)->get_type()->get_name(), "", true)
+ + "Factory";
+ indent_impl(s_service_impl) << "ret." << prop_name(*x_iter) << " := E." << factory_name
+ << ";" << endl;
}
indent_down_impl();
indent_impl(s_service_impl) << "end;" << endl;
}
+ indent_impl(s_service_impl) << "on E: Exception do begin" << endl;
+ indent_up_impl();
+ indent_impl(s_service_impl) << "if events <> nil then events.UnhandledError(E);" << endl;
+ if (!tfunction->is_oneway()) {
+ indent_impl(s_service_impl) << "appx := TApplicationException.Create( TApplicationException.TExceptionType.InternalError, E.Message);" << endl;
+ indent_impl(s_service_impl) << "try" << endl;
+ indent_up_impl();
+ indent_impl(s_service_impl) << "if events <> nil then events.PreWrite;" << endl;
+ indent_impl(s_service_impl) << "msg := Thrift.Protocol.TMessageImpl.Create('" << tfunction->get_name() << "', TMessageType.Exception, seqid);" << endl;
+ indent_impl(s_service_impl) << "oprot.WriteMessageBegin( msg);" << endl;
+ indent_impl(s_service_impl) << "appx.Write(oprot);" << endl;
+ indent_impl(s_service_impl) << "oprot.WriteMessageEnd();" << endl;
+ indent_impl(s_service_impl) << "oprot.Transport.Flush();" << endl;
+ indent_impl(s_service_impl) << "if events <> nil then events.PostWrite;" << endl;
+ indent_impl(s_service_impl) << "Exit;" << endl;
+ indent_down_impl();
+ indent_impl(s_service_impl) << "finally" << endl;
+ indent_up_impl();
+ indent_impl(s_service_impl) << "appx.Free;" << endl;
+ indent_down_impl();
+ indent_impl(s_service_impl) << "end;" << endl;
+ }
+ indent_down_impl();
+ indent_impl(s_service_impl) << "end;" << endl;
+
+ indent_down_impl();
+ indent_impl(s_service_impl) << "end;" << endl;
+
if (!tfunction->is_oneway()) {
if (events_) {
indent_impl(s_service_impl) << "if events <> nil then events.PreWrite;" << endl;