THRIFT-3564: potential core dump in TQTcpServer
Client: C++
Patch: Sebastian Zenker
diff --git a/lib/cpp/src/thrift/qt/TQTcpServer.cpp b/lib/cpp/src/thrift/qt/TQTcpServer.cpp
index a3211df..350198c 100644
--- a/lib/cpp/src/thrift/qt/TQTcpServer.cpp
+++ b/lib/cpp/src/thrift/qt/TQTcpServer.cpp
@@ -20,6 +20,7 @@
#include <thrift/qt/TQTcpServer.h>
#include <thrift/qt/TQIODeviceTransport.h>
+#include <QMetaType>
#include <QTcpSocket>
#include <thrift/cxxfunctional.h>
@@ -60,6 +61,7 @@
shared_ptr<TProtocolFactory> pfact,
QObject* parent)
: QObject(parent), server_(server), processor_(processor), pfact_(pfact) {
+ qRegisterMetaType<QTcpSocket*>("QTcpSocket*");
connect(server.get(), SIGNAL(newConnection()), SLOT(processIncoming()));
}
@@ -91,8 +93,7 @@
connect(connection.get(), SIGNAL(readyRead()), SLOT(beginDecode()));
- // need to use QueuedConnection since we will be deleting the socket in the slot
- connect(connection.get(), SIGNAL(disconnected()), SLOT(socketClosed()), Qt::QueuedConnection);
+ connect(connection.get(), SIGNAL(disconnected()), SLOT(socketClosed()));
}
}
@@ -114,29 +115,34 @@
ctx->oprot_);
} catch (const TTransportException& ex) {
qWarning("[TQTcpServer] TTransportException during processing: '%s'", ex.what());
- ctxMap_.erase(connection);
+ scheduleDeleteConnectionContext(connection);
} catch (...) {
qWarning("[TQTcpServer] Unknown processor exception");
- ctxMap_.erase(connection);
+ scheduleDeleteConnectionContext(connection);
}
}
void TQTcpServer::socketClosed() {
QTcpSocket* connection(qobject_cast<QTcpSocket*>(sender()));
Q_ASSERT(connection);
+ scheduleDeleteConnectionContext(connection);
+}
- if (ctxMap_.find(connection) == ctxMap_.end()) {
- qWarning("[TQTcpServer] Unknown QTcpSocket closed");
- return;
+void TQTcpServer::deleteConnectionContext(QTcpSocket* connection) {
+ const ConnectionContextMap::size_type deleted = ctxMap_.erase(connection);
+ if (0 == deleted) {
+ qWarning("[TQTcpServer] Unknown QTcpSocket");
}
+}
- ctxMap_.erase(connection);
+void TQTcpServer::scheduleDeleteConnectionContext(QTcpSocket* connection) {
+ QMetaObject::invokeMethod(this, "deleteConnectionContext", Qt::QueuedConnection, Q_ARG(QTcpSocket*, connection));
}
void TQTcpServer::finish(shared_ptr<ConnectionContext> ctx, bool healthy) {
if (!healthy) {
qWarning("[TQTcpServer] Processor failed to process data successfully");
- ctxMap_.erase(ctx->connection_.get());
+ deleteConnectionContext(ctx->connection_.get());
}
}
}
diff --git a/lib/cpp/src/thrift/qt/TQTcpServer.h b/lib/cpp/src/thrift/qt/TQTcpServer.h
index ebe6432..081d84a 100644
--- a/lib/cpp/src/thrift/qt/TQTcpServer.h
+++ b/lib/cpp/src/thrift/qt/TQTcpServer.h
@@ -57,19 +57,22 @@
void processIncoming();
void beginDecode();
void socketClosed();
+ void deleteConnectionContext(QTcpSocket* connection);
private:
Q_DISABLE_COPY(TQTcpServer)
struct ConnectionContext;
+ void scheduleDeleteConnectionContext(QTcpSocket* connection);
void finish(boost::shared_ptr<ConnectionContext> ctx, bool healthy);
boost::shared_ptr<QTcpServer> server_;
boost::shared_ptr<TAsyncProcessor> processor_;
boost::shared_ptr<apache::thrift::protocol::TProtocolFactory> pfact_;
- std::map<QTcpSocket*, boost::shared_ptr<ConnectionContext> > ctxMap_;
+ typedef std::map<QTcpSocket*, boost::shared_ptr<ConnectionContext> > ConnectionContextMap;
+ ConnectionContextMap ctxMap_;
};
}
}