comparison src/runguard.cpp @ 228:37d5f4329449

Implement single running instance check to prevent problems with the SQLite database.
author Matti Hamalainen <ccr@tnsp.org>
date Tue, 20 Mar 2018 13:45:21 +0200
parents
children
comparison
equal deleted inserted replaced
227:07e7f254ef16 228:37d5f4329449
1 //
2 // Taken and modified from https://stackoverflow.com/questions/5006547/qt-best-practice-for-a-single-instance-app-protection
3 //
4 #include "runguard.h"
5 #include <QCryptographicHash>
6
7
8 namespace
9 {
10
11 QString generateKeyHash(const QString &key, const QString &salt)
12 {
13 QByteArray data;
14
15 data.append(key.toUtf8());
16 data.append(salt.toUtf8());
17 data = QCryptographicHash::hash(data, QCryptographicHash::Sha1).toHex();
18
19 return data;
20 }
21
22 }
23
24
25 RunGuard::RunGuard(const QString &key)
26 : key(key)
27 , memLockKey(generateKeyHash(key, "_memLockKey"))
28 , sharedmemKey(generateKeyHash(key, "_sharedmemKey"))
29 , sharedMem(sharedmemKey)
30 , memLock(memLockKey, 1)
31 {
32 memLock.acquire();
33
34 QSharedMemory fix(sharedmemKey); // Fix for *nix: http://habrahabr.ru/post/173281/
35 fix.attach();
36
37 memLock.release();
38 }
39
40
41 RunGuard::~RunGuard()
42 {
43 release();
44 }
45
46
47 bool RunGuard::isAnotherRunning()
48 {
49 if (sharedMem.isAttached())
50 return false;
51
52 memLock.acquire();
53
54 const bool isRunning = sharedMem.attach();
55 if (isRunning)
56 sharedMem.detach();
57
58 memLock.release();
59
60 return isRunning;
61 }
62
63
64 bool RunGuard::tryToRun()
65 {
66 if (isAnotherRunning())
67 return false;
68
69 memLock.acquire();
70 const bool result = sharedMem.create(sizeof(quint64));
71 memLock.release();
72
73 if (!result)
74 release();
75
76 return result;
77 }
78
79
80 void RunGuard::release()
81 {
82 memLock.acquire();
83
84 if (sharedMem.isAttached())
85 sharedMem.detach();
86
87 memLock.release();
88 }