Commit 38563f95707b1ee5ff57fc0a6457e5d2d493c937
1 parent
d68708d3
Only allow one instance (per user) to run
Showing
5 changed files
with
91 additions
and
0 deletions
CMakeLists.txt
mainapp.cpp
| ... | ... | @@ -378,6 +378,13 @@ MainApp *MainApp::getMainApp() |
| 378 | 378 | |
| 379 | 379 | void MainApp::start() |
| 380 | 380 | { |
| 381 | +#ifndef NDEBUG | |
| 382 | + if (fuzzFilePath.empty()) | |
| 383 | + { | |
| 384 | + oneInstanceLock.lock(); | |
| 385 | + } | |
| 386 | +#endif | |
| 387 | + | |
| 381 | 388 | timer.start(); |
| 382 | 389 | |
| 383 | 390 | std::map<int, std::shared_ptr<Listener>> listenerMap; // For finding listeners by fd. |
| ... | ... | @@ -516,6 +523,8 @@ void MainApp::start() |
| 516 | 523 | } |
| 517 | 524 | } |
| 518 | 525 | |
| 526 | + oneInstanceLock.unlock(); | |
| 527 | + | |
| 519 | 528 | for(std::shared_ptr<ThreadData> &thread : threads) |
| 520 | 529 | { |
| 521 | 530 | thread->queueQuit(); | ... | ... |
mainapp.h
| ... | ... | @@ -23,6 +23,7 @@ |
| 23 | 23 | #include "configfileparser.h" |
| 24 | 24 | #include "timer.h" |
| 25 | 25 | #include "scopedsocket.h" |
| 26 | +#include "oneinstancelock.h" | |
| 26 | 27 | |
| 27 | 28 | class MainApp |
| 28 | 29 | { |
| ... | ... | @@ -44,6 +45,7 @@ class MainApp |
| 44 | 45 | std::mutex quitMutex; |
| 45 | 46 | std::string fuzzFilePath; |
| 46 | 47 | bool fuzzWebsockets = false; |
| 48 | + OneInstanceLock oneInstanceLock; | |
| 47 | 49 | |
| 48 | 50 | Logger *logger = Logger::getInstance(); |
| 49 | 51 | ... | ... |
oneinstancelock.cpp
0 → 100644
| 1 | +#include "oneinstancelock.h" | |
| 2 | + | |
| 3 | +#include <stdexcept> | |
| 4 | + | |
| 5 | +#include "utils.h" | |
| 6 | + | |
| 7 | +OneInstanceLock::OneInstanceLock() | |
| 8 | +{ | |
| 9 | + std::string dir("/tmp"); | |
| 10 | + | |
| 11 | + char *d = getenv("HOME"); | |
| 12 | + if (d != NULL && d[0] == '/') | |
| 13 | + { | |
| 14 | + dir = std::string(d); | |
| 15 | + } | |
| 16 | + lockFilePath = dir + "/.FlashMQ.lock"; | |
| 17 | +} | |
| 18 | + | |
| 19 | +OneInstanceLock::~OneInstanceLock() | |
| 20 | +{ | |
| 21 | + unlock(); | |
| 22 | +} | |
| 23 | + | |
| 24 | +void OneInstanceLock::lock() | |
| 25 | +{ | |
| 26 | + fd = open(lockFilePath.c_str(), O_RDWR | O_CREAT, 0600); | |
| 27 | + if (fd < 0) | |
| 28 | + throw std::runtime_error(formatString("Can't create '%s': %s", lockFilePath.c_str(), strerror(errno))); | |
| 29 | + | |
| 30 | + struct flock fl; | |
| 31 | + fl.l_start = 0; | |
| 32 | + fl.l_len = 0; | |
| 33 | + fl.l_type = F_WRLCK; | |
| 34 | + fl.l_whence = SEEK_SET; | |
| 35 | + if (fcntl(fd, F_SETLK, &fl) < 0) | |
| 36 | + { | |
| 37 | + throw std::runtime_error("Can't acquire lock: another instance is already running?"); | |
| 38 | + } | |
| 39 | +} | |
| 40 | + | |
| 41 | +void OneInstanceLock::unlock() | |
| 42 | +{ | |
| 43 | + if (fd > 0) | |
| 44 | + { | |
| 45 | + close(fd); | |
| 46 | + fd = 0; | |
| 47 | + if (!lockFilePath.empty()) | |
| 48 | + { | |
| 49 | + if (unlink(lockFilePath.c_str()) < 0) | |
| 50 | + { | |
| 51 | + logger->logf(LOG_ERR, "Can't delete '%': %s", lockFilePath.c_str(), strerror(errno)); | |
| 52 | + } | |
| 53 | + lockFilePath.clear(); | |
| 54 | + } | |
| 55 | + } | |
| 56 | +} | ... | ... |
oneinstancelock.h
0 → 100644
| 1 | +#ifndef ONEINSTANCELOCK_H | |
| 2 | +#define ONEINSTANCELOCK_H | |
| 3 | + | |
| 4 | +#include <fcntl.h> | |
| 5 | +#include <string.h> | |
| 6 | +#include <unistd.h> | |
| 7 | +#include <string> | |
| 8 | +#include "logger.h" | |
| 9 | + | |
| 10 | +class OneInstanceLock | |
| 11 | +{ | |
| 12 | + int fd = -1; | |
| 13 | + std::string lockFilePath; | |
| 14 | + Logger *logger = Logger::getInstance(); | |
| 15 | + | |
| 16 | +public: | |
| 17 | + OneInstanceLock(); | |
| 18 | + ~OneInstanceLock(); | |
| 19 | + void lock(); | |
| 20 | + void unlock(); | |
| 21 | +}; | |
| 22 | + | |
| 23 | +#endif // ONEINSTANCELOCK_H | ... | ... |