diff options
author | Kai Koehne <kai.koehne@theqtcompany.com> | 2015-04-14 16:58:37 +0200 |
---|---|---|
committer | Kai Koehne <kai.koehne@theqtcompany.com> | 2015-04-16 06:47:21 +0000 |
commit | 95ae661cba931a982d12cd68d8b4da392d74bdd0 (patch) | |
tree | 301026fb6c779580f3aca80b7734ce361f4f4744 /src/libs/installer | |
parent | d50e3f94b5b7eea92a8a3bccad926897196c03f8 (diff) |
Windows: Fix crashes in elevated installation
Until Qt 5.5.0, QLocalSocket::waitForReadyRead() immediately returns
when there are still bytesAvailable(). This means our busy loop for
polling new data gets stuck.
To work around this we've been explicitly calling processEvents(),
which however can have undesired side effects: Namely that non-network
events get delivered too, and that 'intermediate' requests are sent
to the server, resulting in the protocol getting out of sync - requests
get replies from intermediate commands, ultimately leading to crashes.
The patch therefore removes the processEvents() call, and instead
works around the QLocalSocket::waitForReadyRead() deficiency by
subclassing.
Task-number: QTIFW-663
Task-number: QTIFW-656
Task-number: QTIFW-659
Change-Id: I4099fa1702cd8dceda954d672c9c3dac0ca7fd66
Reviewed-by: Karsten Heimrich <karsten.heimrich@theqtcompany.com>
Diffstat (limited to 'src/libs/installer')
-rw-r--r-- | src/libs/installer/installer.pro | 3 | ||||
-rw-r--r-- | src/libs/installer/keepaliveobject.cpp | 4 | ||||
-rw-r--r-- | src/libs/installer/localsocket.h | 74 | ||||
-rw-r--r-- | src/libs/installer/remoteobject.cpp | 3 | ||||
-rw-r--r-- | src/libs/installer/remoteobject.h | 4 | ||||
-rw-r--r-- | src/libs/installer/remoteserverconnection.cpp | 7 |
6 files changed, 82 insertions, 13 deletions
diff --git a/src/libs/installer/installer.pro b/src/libs/installer/installer.pro index ac6354309..87af31f3c 100644 --- a/src/libs/installer/installer.pro +++ b/src/libs/installer/installer.pro @@ -123,7 +123,8 @@ HEADERS += packagemanagercore.h \ proxycredentialsdialog.h \ serverauthenticationdialog.h \ keepaliveobject.h \ - systeminfo.h + systeminfo.h \ + localsocket.h SOURCES += packagemanagercore.cpp \ packagemanagercore_p.cpp \ diff --git a/src/libs/installer/keepaliveobject.cpp b/src/libs/installer/keepaliveobject.cpp index 226181120..15af0d724 100644 --- a/src/libs/installer/keepaliveobject.cpp +++ b/src/libs/installer/keepaliveobject.cpp @@ -34,8 +34,8 @@ #include "keepaliveobject.h" #include "remoteclient.h" +#include "localsocket.h" -#include <QLocalSocket> #include <QTimer> namespace QInstaller { @@ -49,7 +49,7 @@ KeepAliveObject::KeepAliveObject() void KeepAliveObject::start() { m_timer = new QTimer(this); - m_socket = new QLocalSocket(this); + m_socket = new LocalSocket(this); connect(m_timer, &QTimer::timeout, [this]() { if (m_socket->state() != QLocalSocket::UnconnectedState) diff --git a/src/libs/installer/localsocket.h b/src/libs/installer/localsocket.h new file mode 100644 index 000000000..bb0337d11 --- /dev/null +++ b/src/libs/installer/localsocket.h @@ -0,0 +1,74 @@ +/************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Installer Framework. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** +** $QT_END_LICENSE$ +** +**************************************************************************/ + +#ifndef LOCALSOCKET_H +#define LOCALSOCKET_H + +#include <QLocalSocket> + +#if defined(Q_OS_WIN) && QT_VERSION < QT_VERSION_CHECK(5,5,0) + +// This is a crude hack to work around QLocalSocket::waitForReadyRead returning instantly +// if there are still bytes left in the buffer. This has been fixed in Qt 5.5.0 ... +class LocalSocket : public QLocalSocket +{ +public: + LocalSocket(QObject *parent = 0) : QLocalSocket(parent), inReadyRead(false) + { + } + + qint64 bytesAvailable() const { + if (inReadyRead) + return 0; + return QLocalSocket::bytesAvailable(); + } + + bool waitForReadyRead(int msecs = 30000) { + inReadyRead = true; + bool result = QLocalSocket::waitForReadyRead(msecs); + inReadyRead = false; + return result; + } + +private: + bool inReadyRead; +}; + +#else + +using LocalSocket = QLocalSocket; + +#endif + +#endif // LOCALSOCKET_H diff --git a/src/libs/installer/remoteobject.cpp b/src/libs/installer/remoteobject.cpp index 581085ab3..add11fa68 100644 --- a/src/libs/installer/remoteobject.cpp +++ b/src/libs/installer/remoteobject.cpp @@ -36,6 +36,7 @@ #include "protocol.h" #include "remoteclient.h" +#include "localsocket.h" #include <QCoreApplication> #include <QElapsedTimer> @@ -73,7 +74,7 @@ bool RemoteObject::authorize() if (m_socket) delete m_socket; - m_socket = new QLocalSocket; + m_socket = new LocalSocket; m_socket->connectToServer(RemoteClient::instance().socketName()); QElapsedTimer stopWatch; diff --git a/src/libs/installer/remoteobject.h b/src/libs/installer/remoteobject.h index f0f8da5fe..57ab0599d 100644 --- a/src/libs/installer/remoteobject.h +++ b/src/libs/installer/remoteobject.h @@ -101,10 +101,6 @@ public: "Bytes expected: %2, Bytes received: %3. Error: %4").arg(name).arg(0) .arg(m_socket->bytesAvailable()).arg(m_socket->errorString())); } -#if defined Q_OS_WIN && QT_VERSION < QT_VERSION_CHECK(5,5,0) - // work around QTBUG-16688 - QCoreApplication::processEvents(); -#endif } Q_ASSERT(command == Protocol::Reply); diff --git a/src/libs/installer/remoteserverconnection.cpp b/src/libs/installer/remoteserverconnection.cpp index 162ebcfdb..cdaf070fd 100644 --- a/src/libs/installer/remoteserverconnection.cpp +++ b/src/libs/installer/remoteserverconnection.cpp @@ -39,6 +39,7 @@ #include "remoteserverconnection_p.h" #include "utils.h" #include "permissionsettings.h" +#include "localsocket.h" #include <QCoreApplication> #include <QDataStream> @@ -71,7 +72,7 @@ private: void RemoteServerConnection::run() { - QLocalSocket socket; + LocalSocket socket; socket.setSocketDescriptor(m_socketDescriptor); QScopedPointer<PermissionSettings> settings; @@ -82,10 +83,6 @@ void RemoteServerConnection::run() if (!receivePacket(&socket, &cmd, &data)) { socket.waitForReadyRead(250); -#if defined(Q_OS_WIN) && QT_VERSION < QT_VERSION_CHECK(5,5,0) - // work around QTBUG-16688 - QCoreApplication::processEvents(); -#endif continue; } |