From 3db3c7b8767f64998fcd48b574729dca90b95fd9 Mon Sep 17 00:00:00 2001 From: Daniel Molkentin Date: Tue, 20 May 2014 17:12:56 +0200 Subject: [PATCH] Update QtSingleApplication and QtLockedFile Fixes stale temp file issues, and is needed for blocking support. --- src/3rdparty/qtlockedfile/README.txt | 2 +- src/3rdparty/qtlockedfile/qtlockedfile.cpp | 41 ++-- src/3rdparty/qtlockedfile/qtlockedfile.h | 41 ++-- src/3rdparty/qtlockedfile/qtlockedfile.pri | 11 + .../qtlockedfile/qtlockedfile_unix.cpp | 42 ++-- .../qtlockedfile/qtlockedfile_win.cpp | 44 ++-- src/3rdparty/qtsingleapplication/README.txt | 2 +- .../qtsingleapplication/qtlocalpeer.cpp | 102 +++++---- .../qtsingleapplication/qtlocalpeer.h | 51 ++--- .../qtsingleapplication.cpp | 206 ++++++++++-------- .../qtsingleapplication/qtsingleapplication.h | 80 +++---- .../qtsingleapplication.pri | 15 ++ .../qtsinglecoreapplication.cpp | 49 +++-- .../qtsinglecoreapplication.h | 43 ++-- .../qtsinglecoreapplication.pri | 14 ++ src/mirall/application.cpp | 3 +- 16 files changed, 404 insertions(+), 342 deletions(-) create mode 100644 src/3rdparty/qtlockedfile/qtlockedfile.pri create mode 100644 src/3rdparty/qtsingleapplication/qtsingleapplication.pri create mode 100644 src/3rdparty/qtsingleapplication/qtsinglecoreapplication.pri diff --git a/src/3rdparty/qtlockedfile/README.txt b/src/3rdparty/qtlockedfile/README.txt index 564b478b17..b89401295b 100644 --- a/src/3rdparty/qtlockedfile/README.txt +++ b/src/3rdparty/qtlockedfile/README.txt @@ -1,5 +1,5 @@ This is the src directory of the QtLockedFile -solution integrated over from Qt's Qt Creator. +solution integrated over from Qt's Qt Creator. It is required by the QtSingleApplication solution. diff --git a/src/3rdparty/qtlockedfile/qtlockedfile.cpp b/src/3rdparty/qtlockedfile/qtlockedfile.cpp index 93fa822d1e..f833ca0d32 100644 --- a/src/3rdparty/qtlockedfile/qtlockedfile.cpp +++ b/src/3rdparty/qtlockedfile/qtlockedfile.cpp @@ -1,32 +1,31 @@ -/************************************************************************** +/**************************************************************************** ** -** This file is part of Qt Creator +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal ** -** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: http://www.qt-project.org/ +** This file is part of Qt Creator. ** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this file. -** Please review the following information to ensure the GNU Lesser General -** Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** -** Other Usage -** -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -**************************************************************************/ +****************************************************************************/ #include "qtlockedfile.h" diff --git a/src/3rdparty/qtlockedfile/qtlockedfile.h b/src/3rdparty/qtlockedfile/qtlockedfile.h index 1609837702..fcfb8cc24f 100644 --- a/src/3rdparty/qtlockedfile/qtlockedfile.h +++ b/src/3rdparty/qtlockedfile/qtlockedfile.h @@ -1,32 +1,31 @@ -/************************************************************************** +/**************************************************************************** ** -** This file is part of Qt Creator +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal ** -** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: http://www.qt-project.org/ +** This file is part of Qt Creator. ** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this file. -** Please review the following information to ensure the GNU Lesser General -** Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** -** Other Usage -** -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -**************************************************************************/ +****************************************************************************/ #ifndef QTLOCKEDFILE_H #define QTLOCKEDFILE_H diff --git a/src/3rdparty/qtlockedfile/qtlockedfile.pri b/src/3rdparty/qtlockedfile/qtlockedfile.pri new file mode 100644 index 0000000000..ad0c2fbabf --- /dev/null +++ b/src/3rdparty/qtlockedfile/qtlockedfile.pri @@ -0,0 +1,11 @@ +INCLUDEPATH += $$PWD +DEPENDPATH += $$PWD +HEADERS += $$PWD/qtlockedfile.h +SOURCES += $$PWD/qtlockedfile.cpp + +unix:SOURCES += $$PWD/qtlockedfile_unix.cpp +win32:SOURCES += $$PWD/qtlockedfile_win.cpp + +win32:contains(TEMPLATE, lib):contains(CONFIG, shared) { + DEFINES += QT_QTLOCKEDFILE_EXPORT=__declspec(dllexport) +} diff --git a/src/3rdparty/qtlockedfile/qtlockedfile_unix.cpp b/src/3rdparty/qtlockedfile/qtlockedfile_unix.cpp index d3efa99fc8..171178b5f1 100644 --- a/src/3rdparty/qtlockedfile/qtlockedfile_unix.cpp +++ b/src/3rdparty/qtlockedfile/qtlockedfile_unix.cpp @@ -1,32 +1,31 @@ -/************************************************************************** +/**************************************************************************** ** -** This file is part of Qt Creator +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal ** -** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: http://www.qt-project.org/ +** This file is part of Qt Creator. ** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this file. -** Please review the following information to ensure the GNU Lesser General -** Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** -** Other Usage -** -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -**************************************************************************/ +****************************************************************************/ #include "qtlockedfile.h" @@ -96,6 +95,7 @@ bool QtLockedFile::unlock() } m_lock_mode = NoLock; + remove(); return true; } diff --git a/src/3rdparty/qtlockedfile/qtlockedfile_win.cpp b/src/3rdparty/qtlockedfile/qtlockedfile_win.cpp index 6d189fb9e7..ae6286fce6 100644 --- a/src/3rdparty/qtlockedfile/qtlockedfile_win.cpp +++ b/src/3rdparty/qtlockedfile/qtlockedfile_win.cpp @@ -1,32 +1,31 @@ -/************************************************************************** +/**************************************************************************** ** -** This file is part of Qt Creator +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal ** -** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: http://www.qt-project.org/ +** This file is part of Qt Creator. ** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this file. -** Please review the following information to ensure the GNU Lesser General -** Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** -** Other Usage -** -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -**************************************************************************/ +****************************************************************************/ #include "qtlockedfile.h" @@ -50,7 +49,7 @@ static QString errorCodeToString(DWORD errorCode) if (data != 0) LocalFree(data); - if (result.endsWith('\n')) + if (result.endsWith(QLatin1Char('\n'))) result.truncate(result.length() - 1); return result; @@ -168,6 +167,7 @@ bool QtLockedFile::unlock() } m_lock_mode = QtLockedFile::NoLock; + remove(); return true; } diff --git a/src/3rdparty/qtsingleapplication/README.txt b/src/3rdparty/qtsingleapplication/README.txt index daf5e1bdf7..b5d8869481 100644 --- a/src/3rdparty/qtsingleapplication/README.txt +++ b/src/3rdparty/qtsingleapplication/README.txt @@ -1,5 +1,5 @@ This is the src directory of the QtSingleApplication solution -integrated over from Qt's Qt Creator project. +integrated over from Qt's Qt Creator project. It additionally requires the QtLockedFile solution. diff --git a/src/3rdparty/qtsingleapplication/qtlocalpeer.cpp b/src/3rdparty/qtsingleapplication/qtlocalpeer.cpp index a9d8c879c0..09c69ce525 100644 --- a/src/3rdparty/qtsingleapplication/qtlocalpeer.cpp +++ b/src/3rdparty/qtsingleapplication/qtlocalpeer.cpp @@ -1,32 +1,31 @@ -/************************************************************************** +/**************************************************************************** ** -** This file is part of Qt Creator +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal ** -** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: http://www.qt-project.org/ +** This file is part of Qt Creator. ** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this file. -** Please review the following information to ensure the GNU Lesser General -** Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** -** Other Usage -** -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -**************************************************************************/ +****************************************************************************/ #include "qtlocalpeer.h" @@ -47,7 +46,31 @@ static PProcessIdToSessionId pProcessIdToSessionId = 0; namespace SharedTools { -const char *QtLocalPeer::ack = "ack"; +static const char ack[] = "ack"; + +QString QtLocalPeer::appSessionId(const QString &appId) +{ + QByteArray idc = appId.toUtf8(); + quint16 idNum = qChecksum(idc.constData(), idc.size()); + //### could do: two 16bit checksums over separate halves of id, for a 32bit result - improved uniqeness probability. Every-other-char split would be best. + + QString res = QLatin1String("qtsingleapplication-") + + QString::number(idNum, 16); +#if defined(Q_OS_WIN) + if (!pProcessIdToSessionId) { + QLibrary lib(QLatin1String("kernel32")); + pProcessIdToSessionId = (PProcessIdToSessionId)lib.resolve("ProcessIdToSessionId"); + } + if (pProcessIdToSessionId) { + DWORD sessionId = 0; + pProcessIdToSessionId(GetCurrentProcessId(), &sessionId); + res += QLatin1Char('-') + QString::number(sessionId, 16); + } +#else + res += QLatin1Char('-') + QString::number(::getuid(), 16); +#endif + return res; +} QtLocalPeer::QtLocalPeer(QObject *parent, const QString &appId) : QObject(parent), id(appId) @@ -55,26 +78,7 @@ QtLocalPeer::QtLocalPeer(QObject *parent, const QString &appId) if (id.isEmpty()) id = QCoreApplication::applicationFilePath(); //### On win, check if this returns .../argv[0] without casefolding; .\MYAPP == .\myapp on Win - QByteArray idc = id.toUtf8(); - quint16 idNum = qChecksum(idc.constData(), idc.size()); - //### could do: two 16bit checksums over separate halves of id, for a 32bit result - improved uniqeness probability. Every-other-char split would be best. - - socketName = QLatin1String("qtsingleapplication-") - + QString::number(idNum, 16); -#if defined(Q_OS_WIN) - if (!pProcessIdToSessionId) { - QLibrary lib("kernel32"); - pProcessIdToSessionId = (PProcessIdToSessionId)lib.resolve("ProcessIdToSessionId"); - } - if (pProcessIdToSessionId) { - DWORD sessionId = 0; - pProcessIdToSessionId(GetCurrentProcessId(), &sessionId); - socketName += QLatin1Char('-') + QString::number(sessionId, 16); - } -#else - socketName += QLatin1Char('-') + QString::number(::getuid(), 16); -#endif - + socketName = appSessionId(id); server = new QLocalServer(this); QString lockName = QDir(QDir::tempPath()).absolutePath() + QLatin1Char('/') + socketName @@ -100,7 +104,7 @@ bool QtLocalPeer::isClient() return false; } -bool QtLocalPeer::sendMessage(const QString &message, int timeout) +bool QtLocalPeer::sendMessage(const QString &message, int timeout, bool block) { if (!isClient()) return false; @@ -130,6 +134,8 @@ bool QtLocalPeer::sendMessage(const QString &message, int timeout) bool res = socket.waitForBytesWritten(timeout); res &= socket.waitForReadyRead(timeout); // wait for ack res &= (socket.read(qstrlen(ack)) == ack); + if (block) // block until peer disconnects + socket.waitForDisconnected(-1); return res; } @@ -140,8 +146,11 @@ void QtLocalPeer::receiveConnection() return; // Why doesn't Qt have a blocking stream that takes care of this shait??? - while (socket->bytesAvailable() < static_cast(sizeof(quint32))) - socket->waitForReadyRead(); + while (socket->bytesAvailable() < static_cast(sizeof(quint32))) { + if (!socket->isValid()) // stale request + return; + socket->waitForReadyRead(1000); + } QDataStream ds(socket); QByteArray uMsg; quint32 remaining; @@ -166,8 +175,7 @@ void QtLocalPeer::receiveConnection() QString message = QString::fromUtf8(uMsg.constData(), uMsg.size()); socket->write(ack, qstrlen(ack)); socket->waitForBytesWritten(1000); - delete socket; - emit messageReceived(message); // ##(might take a long time to return) + emit messageReceived(message, socket); // ##(might take a long time to return) } } // namespace SharedTools diff --git a/src/3rdparty/qtsingleapplication/qtlocalpeer.h b/src/3rdparty/qtsingleapplication/qtlocalpeer.h index b28caad0de..3619363191 100644 --- a/src/3rdparty/qtsingleapplication/qtlocalpeer.h +++ b/src/3rdparty/qtsingleapplication/qtlocalpeer.h @@ -1,34 +1,33 @@ -/************************************************************************** +/**************************************************************************** ** -** This file is part of Qt Creator +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal ** -** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: http://www.qt-project.org/ +** This file is part of Qt Creator. ** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this file. -** Please review the following information to ensure the GNU Lesser General -** Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** -** Other Usage -** -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -**************************************************************************/ +****************************************************************************/ -#include "qtlockedfile.h" +#include #include #include @@ -43,12 +42,13 @@ class QtLocalPeer : public QObject public: explicit QtLocalPeer(QObject *parent = 0, const QString &appId = QString()); bool isClient(); - bool sendMessage(const QString &message, int timeout); + bool sendMessage(const QString &message, int timeout, bool block); QString applicationId() const { return id; } + static QString appSessionId(const QString &appId); Q_SIGNALS: - void messageReceived(const QString &message); + void messageReceived(const QString &message, QObject *socket); protected Q_SLOTS: void receiveConnection(); @@ -58,9 +58,6 @@ protected: QString socketName; QLocalServer* server; QtLockedFile lockFile; - -private: - static const char* ack; }; } // namespace SharedTools diff --git a/src/3rdparty/qtsingleapplication/qtsingleapplication.cpp b/src/3rdparty/qtsingleapplication/qtsingleapplication.cpp index 69e6f32998..9610937ded 100644 --- a/src/3rdparty/qtsingleapplication/qtsingleapplication.cpp +++ b/src/3rdparty/qtsingleapplication/qtsingleapplication.cpp @@ -1,96 +1,123 @@ -/************************************************************************** +/**************************************************************************** ** -** This file is part of Qt Creator +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal ** -** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: http://www.qt-project.org/ +** This file is part of Qt Creator. ** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this file. -** Please review the following information to ensure the GNU Lesser General -** Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** -** Other Usage -** -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -**************************************************************************/ +****************************************************************************/ #include "qtsingleapplication.h" #include "qtlocalpeer.h" -#include +#include + +#include #include +#include +#include namespace SharedTools { -void QtSingleApplication::sysInit(const QString &appId) +static const int instancesSize = 1024; + +static QString instancesLockFilename(const QString &appSessionId) { - actWin = 0; - firstPeer = new QtLocalPeer(this, appId); - connect(firstPeer, SIGNAL(messageReceived(QString)), SIGNAL(messageReceived(QString))); - pidPeer = new QtLocalPeer(this, appId + QLatin1Char('-') + QString::number(QCoreApplication::applicationPid(), 10)); - connect(pidPeer, SIGNAL(messageReceived(QString)), SIGNAL(messageReceived(QString))); + const QChar slash(QLatin1Char('/')); + QString res = QDir::tempPath(); + if (!res.endsWith(slash)) + res += slash; + return res + appSessionId + QLatin1String("-instances"); } - -QtSingleApplication::QtSingleApplication(int &argc, char **argv, bool GUIenabled) - : QApplication(argc, argv, GUIenabled) -{ - sysInit(); -} - - QtSingleApplication::QtSingleApplication(const QString &appId, int &argc, char **argv) - : QApplication(argc, argv) + : QApplication(argc, argv), + firstPeer(-1), + pidPeer(0) { this->appId = appId; - sysInit(appId); + + const QString appSessionId = QtLocalPeer::appSessionId(appId); + + // This shared memory holds a zero-terminated array of active (or crashed) instances + instances = new QSharedMemory(appSessionId, this); + actWin = 0; + block = false; + + // First instance creates the shared memory, later instances attach to it + const bool created = instances->create(instancesSize); + if (!created) { + if (!instances->attach()) { + qWarning() << "Failed to initialize instances shared memory: " + << instances->errorString(); + delete instances; + instances = 0; + return; + } + } + + // QtLockedFile is used to workaround QTBUG-10364 + QtLockedFile lockfile(instancesLockFilename(appSessionId)); + + lockfile.open(QtLockedFile::ReadWrite); + lockfile.lock(QtLockedFile::WriteLock); + qint64 *pids = static_cast(instances->data()); + if (!created) { + // Find the first instance that it still running + // The whole list needs to be iterated in order to append to it + for (; *pids; ++pids) { + if (firstPeer == -1 && isRunning(*pids)) + firstPeer = *pids; + } + } + // Add current pid to list and terminate it + *pids++ = QCoreApplication::applicationPid(); + *pids = 0; + pidPeer = new QtLocalPeer(this, appId + QLatin1Char('-') + + QString::number(QCoreApplication::applicationPid())); + connect(pidPeer, SIGNAL(messageReceived(QString,QObject*)), SIGNAL(messageReceived(QString,QObject*))); + pidPeer->isClient(); + lockfile.unlock(); } - -#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) -QtSingleApplication::QtSingleApplication(int &argc, char **argv, Type type) - : QApplication(argc, argv, type) +QtSingleApplication::~QtSingleApplication() { - sysInit(); + if (!instances) + return; + const qint64 appPid = QCoreApplication::applicationPid(); + QtLockedFile lockfile(instancesLockFilename(QtLocalPeer::appSessionId(appId))); + lockfile.open(QtLockedFile::ReadWrite); + lockfile.lock(QtLockedFile::WriteLock); + // Rewrite array, removing current pid and previously crashed ones + qint64 *pids = static_cast(instances->data()); + qint64 *newpids = pids; + for (; *pids; ++pids) { + if (*pids != appPid && isRunning(*pids)) + *newpids++ = *pids; + } + *newpids = 0; + lockfile.unlock(); } -#endif - - -#if defined(Q_WS_X11) -QtSingleApplication::QtSingleApplication(Display* dpy, Qt::HANDLE visual, Qt::HANDLE colormap) - : QApplication(dpy, visual, colormap) -{ - sysInit(); -} - -QtSingleApplication::QtSingleApplication(Display *dpy, int &argc, char **argv, Qt::HANDLE visual, Qt::HANDLE cmap) - : QApplication(dpy, argc, argv, visual, cmap) -{ - sysInit(); -} - -QtSingleApplication::QtSingleApplication(Display* dpy, const QString &appId, - int argc, char **argv, Qt::HANDLE visual, Qt::HANDLE colormap) - : QApplication(dpy, argc, argv, visual, colormap) -{ - this->appId = appId; - sysInit(appId); -} -#endif bool QtSingleApplication::event(QEvent *event) { @@ -104,31 +131,26 @@ bool QtSingleApplication::event(QEvent *event) bool QtSingleApplication::isRunning(qint64 pid) { - if (pid == -1) - return firstPeer->isClient(); + if (pid == -1) { + pid = firstPeer; + if (pid == -1) + return false; + } QtLocalPeer peer(this, appId + QLatin1Char('-') + QString::number(pid, 10)); return peer.isClient(); } -void QtSingleApplication::initialize(bool) -{ - firstPeer->isClient(); - pidPeer->isClient(); -} - bool QtSingleApplication::sendMessage(const QString &message, int timeout, qint64 pid) { - if (pid == -1) - return firstPeer->sendMessage(message, timeout); + if (pid == -1) { + pid = firstPeer; + if (pid == -1) + return false; + } QtLocalPeer peer(this, appId + QLatin1Char('-') + QString::number(pid, 10)); - return peer.sendMessage(message, timeout); -} - -QString QtSingleApplication::id() const -{ - return firstPeer->applicationId(); + return peer.sendMessage(message, timeout, block); } QString QtSingleApplication::applicationId() const @@ -136,16 +158,20 @@ QString QtSingleApplication::applicationId() const return appId; } +void QtSingleApplication::setBlock(bool value) +{ + block = value; +} + void QtSingleApplication::setActivationWindow(QWidget *aw, bool activateOnMessage) { actWin = aw; - if (activateOnMessage) { - connect(firstPeer, SIGNAL(messageReceived(QString)), this, SLOT(activateWindow())); - connect(pidPeer, SIGNAL(messageReceived(QString)), this, SLOT(activateWindow())); - } else { - disconnect(firstPeer, SIGNAL(messageReceived(QString)), this, SLOT(activateWindow())); - disconnect(pidPeer, SIGNAL(messageReceived(QString)), this, SLOT(activateWindow())); - } + if (!pidPeer) + return; + if (activateOnMessage) + connect(pidPeer, SIGNAL(messageReceived(QString,QObject*)), this, SLOT(activateWindow())); + else + disconnect(pidPeer, SIGNAL(messageReceived(QString,QObject*)), this, SLOT(activateWindow())); } diff --git a/src/3rdparty/qtsingleapplication/qtsingleapplication.h b/src/3rdparty/qtsingleapplication/qtsingleapplication.h index b04b2a138c..9e8d86cf55 100644 --- a/src/3rdparty/qtsingleapplication/qtsingleapplication.h +++ b/src/3rdparty/qtsingleapplication/qtsingleapplication.h @@ -1,38 +1,39 @@ -/************************************************************************** +/**************************************************************************** ** -** This file is part of Qt Creator +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal ** -** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: http://www.qt-project.org/ +** This file is part of Qt Creator. ** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this file. -** Please review the following information to ensure the GNU Lesser General -** Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** -** Other Usage -** -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -**************************************************************************/ +****************************************************************************/ -#ifndef _SHAREDTOOLS_SINGLEAPPLICATION -#define _SHAREDTOOLS_SINGLEAPPLICATION +#ifndef QTSINGLEAPPLICATION_H +#define QTSINGLEAPPLICATION_H #include +QT_FORWARD_DECLARE_CLASS(QSharedMemory) + namespace SharedTools { class QtLocalPeer; @@ -42,50 +43,37 @@ class QtSingleApplication : public QApplication Q_OBJECT public: - QtSingleApplication(int &argc, char **argv, bool GUIenabled = true); QtSingleApplication(const QString &id, int &argc, char **argv); -#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) - QtSingleApplication(int &argc, char **argv, Type type); -#endif -#if defined(Q_WS_X11) - explicit QtSingleApplication(Display *dpy, Qt::HANDLE visual = 0, Qt::HANDLE colormap = 0); - QtSingleApplication(Display *dpy, int &argc, char **argv, Qt::HANDLE visual = 0, Qt::HANDLE cmap = 0); -#endif + ~QtSingleApplication(); bool isRunning(qint64 pid = -1); - QString id() const; - void setActivationWindow(QWidget* aw, bool activateOnMessage = true); QWidget* activationWindow() const; bool event(QEvent *event); QString applicationId() const; + void setBlock(bool value); public Q_SLOTS: bool sendMessage(const QString &message, int timeout = 5000, qint64 pid = -1); void activateWindow(); -//Obsolete methods: -public: - void initialize(bool = true); - -#if defined(Q_WS_X11) - QtSingleApplication(Display* dpy, const QString &id, int argc, char **argv, Qt::HANDLE visual = 0, Qt::HANDLE colormap = 0); -#endif -// end obsolete methods - Q_SIGNALS: - void messageReceived(const QString &message); + void messageReceived(const QString &message, QObject *socket); void fileOpenRequest(const QString &file); private: - void sysInit(const QString &appId = QString()); - QtLocalPeer *firstPeer; + QString instancesFileName(const QString &appId); + + qint64 firstPeer; + QSharedMemory *instances; QtLocalPeer *pidPeer; QWidget *actWin; QString appId; + bool block; }; } // namespace SharedTools -#endif // _SHAREDTOOLS_SINGLEAPPLICATION + +#endif // QTSINGLEAPPLICATION_H diff --git a/src/3rdparty/qtsingleapplication/qtsingleapplication.pri b/src/3rdparty/qtsingleapplication/qtsingleapplication.pri new file mode 100644 index 0000000000..c807763dce --- /dev/null +++ b/src/3rdparty/qtsingleapplication/qtsingleapplication.pri @@ -0,0 +1,15 @@ +INCLUDEPATH += $$PWD +DEPENDPATH += $$PWD +HEADERS += $$PWD/qtsingleapplication.h $$PWD/qtlocalpeer.h +SOURCES += $$PWD/qtsingleapplication.cpp $$PWD/qtlocalpeer.cpp + +QT *= network +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +gotqtlockedfile = $$find(HEADERS, .*qtlockedfile.h) +isEmpty(gotqtlockedfile):include(../qtlockedfile/qtlockedfile.pri) + + +win32:contains(TEMPLATE, lib):contains(CONFIG, shared) { + DEFINES += QT_QTSINGLEAPPLICATION_EXPORT=__declspec(dllexport) +} diff --git a/src/3rdparty/qtsingleapplication/qtsinglecoreapplication.cpp b/src/3rdparty/qtsingleapplication/qtsinglecoreapplication.cpp index 96af121e98..25a511f6c3 100644 --- a/src/3rdparty/qtsingleapplication/qtsinglecoreapplication.cpp +++ b/src/3rdparty/qtsingleapplication/qtsinglecoreapplication.cpp @@ -1,32 +1,31 @@ -/************************************************************************** +/**************************************************************************** ** -** This file is part of Qt Creator +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal ** -** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: http://www.qt-project.org/ +** This file is part of Qt Creator. ** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this file. -** Please review the following information to ensure the GNU Lesser General -** Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** -** Other Usage -** -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -**************************************************************************/ +****************************************************************************/ #include "qtsinglecoreapplication.h" #include "qtlocalpeer.h" @@ -37,6 +36,7 @@ QtSingleCoreApplication::QtSingleCoreApplication(int &argc, char **argv) : QCoreApplication(argc, argv) { peer = new QtLocalPeer(this); + block = false; connect(peer, SIGNAL(messageReceived(QString)), SIGNAL(messageReceived(QString))); } @@ -57,7 +57,7 @@ bool QtSingleCoreApplication::isRunning() bool QtSingleCoreApplication::sendMessage(const QString &message, int timeout) { - return peer->sendMessage(message, timeout); + return peer->sendMessage(message, timeout, block); } @@ -66,4 +66,9 @@ QString QtSingleCoreApplication::id() const return peer->applicationId(); } +void QtSingleCoreApplication::setBlock(bool value) +{ + block = value; +} + } // namespace SharedTools diff --git a/src/3rdparty/qtsingleapplication/qtsinglecoreapplication.h b/src/3rdparty/qtsingleapplication/qtsinglecoreapplication.h index 373f693bf2..1575032121 100644 --- a/src/3rdparty/qtsingleapplication/qtsinglecoreapplication.h +++ b/src/3rdparty/qtsingleapplication/qtsinglecoreapplication.h @@ -1,32 +1,31 @@ -/************************************************************************** +/**************************************************************************** ** -** This file is part of Qt Creator +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal ** -** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: http://www.qt-project.org/ +** This file is part of Qt Creator. ** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this file. -** Please review the following information to ensure the GNU Lesser General -** Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** -** Other Usage -** -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -**************************************************************************/ +****************************************************************************/ #include @@ -44,6 +43,7 @@ public: bool isRunning(); QString id() const; + void setBlock(bool value); public Q_SLOTS: bool sendMessage(const QString &message, int timeout = 5000); @@ -55,6 +55,7 @@ Q_SIGNALS: private: QtLocalPeer* peer; + bool block; }; } // namespace SharedTools diff --git a/src/3rdparty/qtsingleapplication/qtsinglecoreapplication.pri b/src/3rdparty/qtsingleapplication/qtsinglecoreapplication.pri new file mode 100644 index 0000000000..3d6301b29c --- /dev/null +++ b/src/3rdparty/qtsingleapplication/qtsinglecoreapplication.pri @@ -0,0 +1,14 @@ +INCLUDEPATH += $$PWD +DEPENDPATH += $$PWD +HEADERS += $$PWD/qtsinglecoreapplication.h $$PWD/qtlocalpeer.h +SOURCES += $$PWD/qtsinglecoreapplication.cpp $$PWD/qtlocalpeer.cpp + +QT *= network + +gotqtlockedfile = $$find(HEADERS, .*qtlockedfile.h) +isEmpty(gotqtlockedfile):include(../qtlockedfile/qtlockedfile.pri) + + +win32:contains(TEMPLATE, lib):contains(CONFIG, shared) { + DEFINES += QT_QTSINGLECOREAPPLICATION_EXPORT=__declspec(dllexport) +} diff --git a/src/mirall/application.cpp b/src/mirall/application.cpp index 7b0a6f1492..86b8f85c96 100644 --- a/src/mirall/application.cpp +++ b/src/mirall/application.cpp @@ -77,7 +77,7 @@ QString applicationTrPath() // ---------------------------------------------------------------------------------- Application::Application(int &argc, char **argv) : - SharedTools::QtSingleApplication(argc, argv), + SharedTools::QtSingleApplication(Theme::instance()->appName() ,argc, argv), _gui(0), _theme(Theme::instance()), _helpOnly(false), @@ -97,7 +97,6 @@ Application::Application(int &argc, char **argv) : //no need to waste time; if ( _helpOnly ) return; - initialize(); if (isRunning()) return;