[
https://issues.apache.org/jira/browse/THRIFT-4384?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16264278#comment-16264278
]
Michael Eiler commented on THRIFT-4384:
---------------------------------------
Currently I solved the problem for us like shown here:
{code:patch}
diff --git a/compiler/cpp/src/thrift/generate/t_cpp_generator.cc
b/compiler/cpp/src/thrift/generate/t_cpp_generator.cc
index cbe8da2..515e0e2 100644
--- a/compiler/cpp/src/thrift/generate/t_cpp_generator.cc
+++ b/compiler/cpp/src/thrift/generate/t_cpp_generator.cc
@@ -1616,6 +1616,8 @@ void t_cpp_generator::generate_service(t_service*
tservice) {
<< "namespace apache { namespace thrift { namespace async {" <<
endl
<< "class TAsyncChannel;" << endl << "}}}" << endl;
}
+ f_header_ << "#include <boost/make_shared.hpp>" << endl;
+ f_header_ << "#include <boost/shared_ptr.hpp>" << endl;
f_header_ << "#include <thrift/TDispatchProcessor.h>" << endl;
if (gen_cob_style_) {
f_header_ << "#include <thrift/async/TAsyncDispatchProcessor.h>" << endl;
@@ -2169,7 +2171,14 @@ void t_cpp_generator::generate_service_client(t_service*
tservice, string style)
indent_up();
if (style != "Cob") {
f_header_ << indent() << service_name_ << style << "Client" <<
short_suffix << "(" << prot_ptr
- << " prot) ";
+ << " prot";
+ if (style == "Concurrent") {
+ f_header_ << ",
boost::shared_ptr<::apache::thrift::async::TConcurrentClientSyncInfo> sync =
boost::make_shared<::apache::thrift::async::TConcurrentClientSyncInfo>()"
+ << ") : sync_(sync) ";
+ }
+ else {
+ f_header_ << ") ";
+ }
if (extends.empty()) {
f_header_ << "{" << endl;
@@ -2182,7 +2191,15 @@ void t_cpp_generator::generate_service_client(t_service*
tservice, string style)
}
f_header_ << indent() << service_name_ << style << "Client" <<
short_suffix << "(" << prot_ptr
- << " iprot, " << prot_ptr << " oprot) ";
+ << " iprot, " << prot_ptr << " oprot";
+ if (style == "Concurrent") {
+ f_header_ << ",
boost::shared_ptr<::apache::thrift::async::TConcurrentClientSyncInfo> sync =
boost::make_shared<::apache::thrift::async::TConcurrentClientSyncInfo>()"
+ << ") : sync_(sync) ";
+ }
+ else {
+ f_header_ << ") ";
+ }
+
if (extends.empty()) {
f_header_ << "{" << endl;
f_header_ << indent() << " setProtocol" << short_suffix <<
"(iprot,oprot);" << endl
@@ -2328,7 +2345,7 @@ void t_cpp_generator::generate_service_client(t_service*
tservice, string style)
if (style == "Concurrent") {
f_header_ <<
- indent() << "::apache::thrift::async::TConcurrentClientSyncInfo
sync_;"<<endl;
+ indent() <<
"boost::shared_ptr<::apache::thrift::async::TConcurrentClientSyncInfo>
sync_;"<<endl;
}
indent_down();
}
@@ -2434,7 +2451,7 @@ void t_cpp_generator::generate_service_client(t_service*
tservice, string style)
string cseqidVal = "0";
if (style == "Concurrent") {
if (!(*f_iter)->is_oneway()) {
- cseqidVal = "this->sync_.generateSeqId()";
+ cseqidVal = "this->sync_->generateSeqId()";
}
}
// Serialize the request
@@ -2442,7 +2459,7 @@ void t_cpp_generator::generate_service_client(t_service*
tservice, string style)
indent() << "int32_t cseqid = " << cseqidVal << ";" << endl;
if(style == "Concurrent") {
out <<
- indent() << "::apache::thrift::async::TConcurrentSendSentry
sentry(&this->sync_);" << endl;
+ indent() << "::apache::thrift::async::TConcurrentSendSentry
sentry(this->sync_.get());" << endl;
}
if (style == "Cob") {
out <<
@@ -2507,7 +2524,7 @@ void t_cpp_generator::generate_service_client(t_service*
tservice, string style)
endl <<
indent() << "// the read mutex gets dropped and reacquired as part
of waitForWork()" << endl <<
indent() << "// The destructor of this sentry wakes up other
clients" << endl <<
- indent() << "::apache::thrift::async::TConcurrentRecvSentry
sentry(&this->sync_, seqid);" << endl;
+ indent() << "::apache::thrift::async::TConcurrentRecvSentry
sentry(this->sync_.get(), seqid);" << endl;
}
if (style == "Cob" && !gen_no_client_completion_) {
out << indent() << "bool completed = false;" << endl << endl <<
indent() << "try {";
@@ -2517,7 +2534,7 @@ void t_cpp_generator::generate_service_client(t_service*
tservice, string style)
if (style == "Concurrent") {
out <<
indent() << "while(true) {" << endl <<
- indent() << " if(!this->sync_.getPending(fname, mtype, rseqid))
{" << endl;
+ indent() << " if(!this->sync_->getPending(fname, mtype, rseqid))
{" << endl;
indent_up();
indent_up();
}
@@ -2661,10 +2678,10 @@ void
t_cpp_generator::generate_service_client(t_service* tservice, string style)
out <<
indent() << " }" << endl <<
indent() << " // seqid != rseqid" << endl <<
- indent() << " this->sync_.updatePending(fname, mtype, rseqid);"
<< endl <<
+ indent() << " this->sync_->updatePending(fname, mtype, rseqid);"
<< endl <<
endl <<
indent() << " // this will temporarily unlock the readMutex, and
let other clients get work done" << endl <<
- indent() << " this->sync_.waitForWork(seqid);" << endl <<
+ indent() << " this->sync_->waitForWork(seqid);" << endl <<
indent() << "} // end while(true)" << endl;
}
if (style == "Cob" && !gen_no_client_completion_) {
{code}
(
https://github.com/MichaelE1000/thrift/commit/44ec66e550d90cf8e0074cd46769b5be0d29253b
)
Do you see any issues with this approach?
Best Regards
> Using multiple services simultaneously is not thread-safe.
> ----------------------------------------------------------
>
> Key: THRIFT-4384
> URL: https://issues.apache.org/jira/browse/THRIFT-4384
> Project: Thrift
> Issue Type: Bug
> Components: C++ - Compiler, C++ - Library
> Affects Versions: 0.10.0
> Environment: Should affect all platforms but has been noticed first
> on Windows, x86_64.
> Reporter: Michael Eiler
> Priority: Critical
> Fix For: 0.10.0, 0.11.0
>
>
> I'm using the generated *ServiceConcurrentClient classes. They should allow
> me to call multiple functions at the same time.
> The issue as that the ::apache::thrift::async::TConcurrentClientSyncInfo
> class is a member of the generated service. If I have a project with multiple
> services sharing the same connection (protocol) with each other, the services
> will not be mutually excluded from reading on the same socket.
> I did a small test with patching the generated code and injecting the same
> instance of TConcurrentClientSyncInfo into all my services and everything was
> fine.
> Question: Do you need a small project to reproduce this or is it obvious
> enough? Just check out any generated code and you will see that the
> TConcurrentClientSyncInfo is not shared between different services.
--
This message was sent by Atlassian JIRA
(v6.4.14#64029)