From 5b469aa3c4d6b9c68feb9cf92d03614077518894 Mon Sep 17 00:00:00 2001 From: Kimmo Karvinen Date: Tue, 31 Mar 2015 17:14:33 +0300 Subject: Fixed a crash when destroying the QWebSocketServer Lifetime of incoming QTcpSocket/QSslSocket are managed by the QTcpServer/QSslServer and thus the QWebSocketPrivate should clear the pointer to the socket when the socket is destroyed. Added auto test for the crash. Task-number: QTBUG-45331 Change-Id: I6e30e7cdcca22aa810ccc1a1d4d7d77c7cb2c349 Reviewed-by: Steven Ceuppens Reviewed-by: Liang Qi --- src/websockets/qwebsocket_p.cpp | 11 +++++++ src/websockets/qwebsocket_p.h | 2 ++ .../auto/qwebsocketserver/tst_qwebsocketserver.cpp | 34 ++++++++++++++++++++++ 3 files changed, 47 insertions(+) diff --git a/src/websockets/qwebsocket_p.cpp b/src/websockets/qwebsocket_p.cpp index ced197e..76a5882 100644 --- a/src/websockets/qwebsocket_p.cpp +++ b/src/websockets/qwebsocket_p.cpp @@ -542,6 +542,10 @@ void QWebSocketPrivate::makeConnections(const QTcpSocket *pTcpSocket) QObject::connect(pTcpSocket, &QAbstractSocket::aboutToClose, q, &QWebSocket::aboutToClose); QObject::connect(pTcpSocket, &QAbstractSocket::bytesWritten, q, &QWebSocket::bytesWritten); + + QObjectPrivate::connect(pTcpSocket, &QObject::destroyed, + this, &QWebSocketPrivate::socketDestroyed); + //catch signals QObjectPrivate::connect(pTcpSocket, &QAbstractSocket::stateChanged, this, &QWebSocketPrivate::processStateChanged); @@ -1048,6 +1052,13 @@ void QWebSocketPrivate::processStateChanged(QAbstractSocket::SocketState socketS } } +void QWebSocketPrivate::socketDestroyed(QObject *socket) +{ + Q_ASSERT(m_pSocket); + if (m_pSocket.data() == socket) + m_pSocket.take(); +} + /*! \internal */ diff --git a/src/websockets/qwebsocket_p.h b/src/websockets/qwebsocket_p.h index f13e08d..85d3f49 100644 --- a/src/websockets/qwebsocket_p.h +++ b/src/websockets/qwebsocket_p.h @@ -162,6 +162,8 @@ private: void setSocketState(QAbstractSocket::SocketState state); void setErrorString(const QString &errorString); + void socketDestroyed(QObject *socket); + void processData(); void processPing(const QByteArray &data); void processPong(const QByteArray &data); diff --git a/tests/auto/qwebsocketserver/tst_qwebsocketserver.cpp b/tests/auto/qwebsocketserver/tst_qwebsocketserver.cpp index f585620..8ee0a36 100644 --- a/tests/auto/qwebsocketserver/tst_qwebsocketserver.cpp +++ b/tests/auto/qwebsocketserver/tst_qwebsocketserver.cpp @@ -64,6 +64,7 @@ private Q_SLOTS: void tst_listening(); void tst_connectivity(); void tst_maxPendingConnections(); + void tst_serverDestroyedWhileSocketConnected(); }; tst_QWebSocketServer::tst_QWebSocketServer() @@ -350,6 +351,39 @@ void tst_QWebSocketServer::tst_maxPendingConnections() QCOMPARE(serverAcceptErrorSpy.count(), 0); } +void tst_QWebSocketServer::tst_serverDestroyedWhileSocketConnected() +{ + QWebSocketServer * server = new QWebSocketServer(QString(), QWebSocketServer::NonSecureMode); + QSignalSpy serverConnectionSpy(server, SIGNAL(newConnection())); + QSignalSpy corsAuthenticationSpy(server, + SIGNAL(originAuthenticationRequired(QWebSocketCorsAuthenticator*))); + QSignalSpy serverClosedSpy(server, SIGNAL(closed())); + + QWebSocket socket; + QSignalSpy socketConnectedSpy(&socket, SIGNAL(connected())); + QSignalSpy socketDisconnectedSpy(&socket, SIGNAL(disconnected())); + + QVERIFY(server->listen()); + QCOMPARE(server->serverAddress(), QHostAddress(QHostAddress::Any)); + QCOMPARE(server->serverUrl(), QUrl(QStringLiteral("ws://") + QHostAddress(QHostAddress::LocalHost).toString() + + QStringLiteral(":").append(QString::number(server->serverPort())))); + + socket.open(server->serverUrl().toString()); + + if (socketConnectedSpy.count() == 0) + QVERIFY(socketConnectedSpy.wait()); + QCOMPARE(socket.state(), QAbstractSocket::ConnectedState); + QCOMPARE(serverConnectionSpy.count(), 1); + QCOMPARE(corsAuthenticationSpy.count(), 1); + + QCOMPARE(serverClosedSpy.count(), 0); + + delete server; + + if (socketDisconnectedSpy.count() == 0) + QVERIFY(socketDisconnectedSpy.wait()); + QCOMPARE(socketDisconnectedSpy.count(), 1); +} QTEST_MAIN(tst_QWebSocketServer) -- cgit v1.2.1