Commit 38563f95707b1ee5ff57fc0a6457e5d2d493c937

Authored by Wiebe Cazemier
1 parent d68708d3

Only allow one instance (per user) to run

CMakeLists.txt
... ... @@ -35,6 +35,7 @@ add_executable(FlashMQ
35 35 unscopedlock.cpp
36 36 scopedsocket.cpp
37 37 bindaddr.cpp
  38 + oneinstancelock.cpp
38 39 )
39 40  
40 41 target_link_libraries(FlashMQ pthread dl ssl crypto)
... ...
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
... ...