Commit 2d6f005d authored by Don Gagne's avatar Don Gagne Committed by GitHub

Merge pull request #4271 from DonLakeFlyer/RunGuard

Single instance app guarding mechanism
parents d1b3e41f a0907e46
......@@ -529,6 +529,7 @@ HEADERS += \
src/Joystick/JoystickSDL.h \
src/QGCFileDialog.h \
src/QGCMessageBox.h \
src/RunGuard.h \
src/ViewWidgets/CustomCommandWidget.h \
src/ViewWidgets/CustomCommandWidgetController.h \
src/ViewWidgets/ViewWidgetController.h \
......@@ -677,6 +678,7 @@ SOURCES += \
src/GPS/RTCM/RTCMMavlink.cc \
src/Joystick/JoystickSDL.cc \
src/QGCFileDialog.cc \
src/RunGuard.cc \
src/ViewWidgets/CustomCommandWidget.cc \
src/ViewWidgets/CustomCommandWidgetController.cc \
src/ViewWidgets/ViewWidgetController.cc \
......
/****************************************************************************
*
* (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
#include "RunGuard.h"
#include <QCryptographicHash>
namespace
{
QString generateKeyHash( const QString& key, const QString& salt )
{
QByteArray data;
data.append( key.toUtf8() );
data.append( salt.toUtf8() );
data = QCryptographicHash::hash( data, QCryptographicHash::Sha1 ).toHex();
return data;
}
}
RunGuard::RunGuard( const QString& key )
: key( key )
, memLockKey( generateKeyHash( key, "_memLockKey" ) )
, sharedmemKey( generateKeyHash( key, "_sharedmemKey" ) )
, sharedMem( sharedmemKey )
, memLock( memLockKey, 1 )
{
memLock.acquire();
{
QSharedMemory fix( sharedmemKey ); // Fix for *nix: http://habrahabr.ru/post/173281/
fix.attach();
}
memLock.release();
}
RunGuard::~RunGuard()
{
release();
}
bool RunGuard::isAnotherRunning()
{
if ( sharedMem.isAttached() )
return false;
memLock.acquire();
const bool isRunning = sharedMem.attach();
if ( isRunning )
sharedMem.detach();
memLock.release();
return isRunning;
}
bool RunGuard::tryToRun()
{
if ( isAnotherRunning() ) // Extra check
return false;
memLock.acquire();
const bool result = sharedMem.create( sizeof( quint64 ) );
memLock.release();
if ( !result )
{
release();
return false;
}
return true;
}
void RunGuard::release()
{
memLock.acquire();
if ( sharedMem.isAttached() )
sharedMem.detach();
memLock.release();
}
/****************************************************************************
*
* (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
#ifndef RunGuard_H
#define RunGuard_H
#include <QObject>
#include <QSharedMemory>
#include <QSystemSemaphore>
class RunGuard
{
public:
RunGuard( const QString& key );
~RunGuard();
bool isAnotherRunning();
bool tryToRun();
void release();
private:
const QString key;
const QString memLockKey;
const QString sharedmemKey;
QSharedMemory sharedMem;
QSystemSemaphore memLock;
Q_DISABLE_COPY( RunGuard )
};
#endif
......@@ -27,10 +27,9 @@
#include "QGCApplication.h"
#include "AppMessages.h"
#define SINGLE_INSTANCE_PORT 14499
#ifndef __mobile__
#include "QGCSerialPortInfo.h"
#include "RunGuard.h"
#endif
#ifdef UNITTEST_BUILD
......@@ -103,6 +102,13 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved)
int main(int argc, char *argv[])
{
#ifndef __mobile__
RunGuard guard("QGroundControlRunGuardKey");
if (!guard.tryToRun()) {
return 0;
}
#endif
#ifdef Q_OS_UNIX
//Force writing to the console on UNIX/BSD devices
if (!qEnvironmentVariableIsSet("QT_LOGGING_TO_CONSOLE"))
......@@ -112,16 +118,6 @@ int main(int argc, char *argv[])
// install the message handler
AppMessages::installHandler();
#ifndef __mobile__
//-- Test for another instance already running. If that's the case, we simply exit.
QHostAddress host("127.0.0.1");
QUdpSocket socket;
if(!socket.bind(host, SINGLE_INSTANCE_PORT, QAbstractSocket::DontShareAddress)) {
qWarning() << "Another instance already running. Exiting.";
exit(-1);
}
#endif
#ifdef Q_OS_MAC
#ifndef __ios__
// Prevent Apple's app nap from screwing us over
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment