summaryrefslogtreecommitdiffstats
path: root/src/libs/installer
diff options
context:
space:
mode:
authorKai Koehne <kai.koehne@theqtcompany.com>2015-04-14 16:58:37 +0200
committerKai Koehne <kai.koehne@theqtcompany.com>2015-04-16 06:47:21 +0000
commit95ae661cba931a982d12cd68d8b4da392d74bdd0 (patch)
tree301026fb6c779580f3aca80b7734ce361f4f4744 /src/libs/installer
parentd50e3f94b5b7eea92a8a3bccad926897196c03f8 (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.pro3
-rw-r--r--src/libs/installer/keepaliveobject.cpp4
-rw-r--r--src/libs/installer/localsocket.h74
-rw-r--r--src/libs/installer/remoteobject.cpp3
-rw-r--r--src/libs/installer/remoteobject.h4
-rw-r--r--src/libs/installer/remoteserverconnection.cpp7
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;
}