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
| @@ -35,6 +35,7 @@ add_executable(FlashMQ | @@ -35,6 +35,7 @@ add_executable(FlashMQ | ||
| 35 | unscopedlock.cpp | 35 | unscopedlock.cpp |
| 36 | scopedsocket.cpp | 36 | scopedsocket.cpp |
| 37 | bindaddr.cpp | 37 | bindaddr.cpp |
| 38 | + oneinstancelock.cpp | ||
| 38 | ) | 39 | ) |
| 39 | 40 | ||
| 40 | target_link_libraries(FlashMQ pthread dl ssl crypto) | 41 | target_link_libraries(FlashMQ pthread dl ssl crypto) |
mainapp.cpp
| @@ -378,6 +378,13 @@ MainApp *MainApp::getMainApp() | @@ -378,6 +378,13 @@ MainApp *MainApp::getMainApp() | ||
| 378 | 378 | ||
| 379 | void MainApp::start() | 379 | void MainApp::start() |
| 380 | { | 380 | { |
| 381 | +#ifndef NDEBUG | ||
| 382 | + if (fuzzFilePath.empty()) | ||
| 383 | + { | ||
| 384 | + oneInstanceLock.lock(); | ||
| 385 | + } | ||
| 386 | +#endif | ||
| 387 | + | ||
| 381 | timer.start(); | 388 | timer.start(); |
| 382 | 389 | ||
| 383 | std::map<int, std::shared_ptr<Listener>> listenerMap; // For finding listeners by fd. | 390 | std::map<int, std::shared_ptr<Listener>> listenerMap; // For finding listeners by fd. |
| @@ -516,6 +523,8 @@ void MainApp::start() | @@ -516,6 +523,8 @@ void MainApp::start() | ||
| 516 | } | 523 | } |
| 517 | } | 524 | } |
| 518 | 525 | ||
| 526 | + oneInstanceLock.unlock(); | ||
| 527 | + | ||
| 519 | for(std::shared_ptr<ThreadData> &thread : threads) | 528 | for(std::shared_ptr<ThreadData> &thread : threads) |
| 520 | { | 529 | { |
| 521 | thread->queueQuit(); | 530 | thread->queueQuit(); |
mainapp.h
| @@ -23,6 +23,7 @@ | @@ -23,6 +23,7 @@ | ||
| 23 | #include "configfileparser.h" | 23 | #include "configfileparser.h" |
| 24 | #include "timer.h" | 24 | #include "timer.h" |
| 25 | #include "scopedsocket.h" | 25 | #include "scopedsocket.h" |
| 26 | +#include "oneinstancelock.h" | ||
| 26 | 27 | ||
| 27 | class MainApp | 28 | class MainApp |
| 28 | { | 29 | { |
| @@ -44,6 +45,7 @@ class MainApp | @@ -44,6 +45,7 @@ class MainApp | ||
| 44 | std::mutex quitMutex; | 45 | std::mutex quitMutex; |
| 45 | std::string fuzzFilePath; | 46 | std::string fuzzFilePath; |
| 46 | bool fuzzWebsockets = false; | 47 | bool fuzzWebsockets = false; |
| 48 | + OneInstanceLock oneInstanceLock; | ||
| 47 | 49 | ||
| 48 | Logger *logger = Logger::getInstance(); | 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 |