4

Is there a platform independent way in C++11 (boost is available) to make sure that only one instance of an application is started at a time? (I'd prefer not to run with the "file and (f)lock" method as it requires platform specific code, but I will do so if there is no better way.)

There is no (simple) other way like an unavailable port that I can use as a criterion in my scenario neither. And yes, I am aware of DOS problems - so no need to point those out.

I found the following similar question suggesting a solution with boost. The solution has two problems though:

  • Minor: It seems a call to shared_memory_object::remove("shared_memory"); is missing (in the case "the race was won"). But I am not really familiar with boost::interprocess, so maybe I am wrong?!
  • Major: If the program crashes the shared memory is still existing and thus the next instance of the program will fail to start.

I also found this question. No answer there that excites me. But it's a C++98 question so maybe with C++11 or boost there is a new/different way now?

Community
  • 1
  • 1
DrP3pp3r
  • 803
  • 9
  • 33
  • 2
    Maybe this answer excites you? [How To Limit The Number Of Running Instances In C++](http://stackoverflow.com/questions/22545789/how-to-limit-the-number-of-running-instances-in-c/22545891#22545891) – sehe Sep 16 '14 at 09:16
  • @sehe: In that answer you mentioned that after _kill -9_ the semaphore needs to be removed "manually". Fair enough. What about in case of a program crash? I assume not every kind of crash can be handled with a signal?! – DrP3pp3r Sep 18 '14 at 06:27
  • Yes, there is the usual ritual with [termination handlers](http://pubs.opengroup.org/onlinepubs/009695399/functions/atexit.html) and signal handlers. To be completely safe, you should probably detect stale IPC objects and handle that situation. It's about the robustness vs. convenience trade-off, for the large part. – sehe Sep 18 '14 at 06:37

2 Answers2

4

You can do file locking in platform independent way with boost.

Lock a file or its own executable.

Community
  • 1
  • 1
Maxim Egorushkin
  • 131,725
  • 17
  • 180
  • 271
  • Implemented it now in a helper class, small solution, works great! Thx! `createFileIfNotExisting(filePath); m_flock = boost::interprocess::file_lock(filePath.c_str()); const auto couldLock = m_flock.try_lock(); if(!couldLock) { throw Exception("Unable to lock file!"); }` – DrP3pp3r Oct 01 '14 at 13:41
1

You can bind to a certain port, for example, using ASIO:

#include <iostream>
#include <boost/asio/ip/udp.hpp>
#include <boost/asio/io_service.hpp>

int main()
{
    boost::asio::io_service io;
    boost::asio::ip::udp::socket sock(io);
    sock.open(boost::asio::ip::udp::v4());
    boost::system::error_code ec;
    sock.bind({boost::asio::ip::udp::v4(), /*your port here*/}, ec);
    if (ec)
        std::cout << "Not mine\n";
    else
        std::cout << "It's mine\n";
    return 0;
}

If it succeeds, then it's the first application, otherwise it's already running.

Jamboree
  • 5,139
  • 2
  • 16
  • 36
  • 4
    There is at least 1 in 65535 chance that another application uses the same port. – Maxim Egorushkin Sep 17 '14 at 09:23
  • Also using a port just for enforcing a single instance seems to be a waste (of course depending on the environment you're running in). Using other resources for this purpose (semaphores, files/file handles, ...) creates similar problems, but the number of available ports can't be increased. For other resources it can be possible to increase their number. – DrP3pp3r Sep 18 '14 at 06:39