Single Instance Application in QT

Single instance applications are fun in any programming language. Let’s take QT as example. One could just create a server and depending on whether it can listen, determine if another instance is running. Something like this:

server = new QLocalServer();
bool serverListening = server.listen("SomeName");

if (!serverListening) {
  //hey, I'm walkin over here
}

And that’s it. Only if it would be this easy.

This code might fail on Unix with AddressInUseError if there was a previous application crash. This means we need to complicate code a bit:

server = new QLocalServer();
bool serverListening = server.listen("SomeName");
if (!serverListening && (server->serverError() == QAbstractSocket::AddressInUseError)) {
  QLocalServer::removeServer(serverName); //cleanup
  serverListening = _server->listen(serverName); //try again
}

if (!serverListening) {
  //hey, I'm walkin over here
}

But fun wouldn’t be complete if that was all. You see, Windows have issues of their own. As implemented in QT, you can actually have multiple listeners at the same time. Failure to listen will never happen there.

Unfortunately this is a bit more complicated and you can really go wild solving this issue – even so far as to involve QSystemSemaphore with it’s portability and thread blocking issues.

Or you can go with solution that works 99% of the time – directly calling into CreateMutexW API.

Modifying code in the following manner will do the trick:

server = new QLocalServer();
bool serverListening = server.listen("SomeName");
if (!serverListening && (server->serverError() == QAbstractSocket::AddressInUseError)) {
  QLocalServer::removeServer(serverName); //cleanup
  serverListening = _server->listen(serverName); //try again
}

#if defined(Q_OS_WIN)
  if (serverListening) {
    CreateMutexW(nullptr, true, reinterpret_cast<LPCWSTR>(serverName.utf16()));
    if (GetLastError() == ERROR_ALREADY_EXISTS) { //someone has this Mutex
      server->close(); //disable server
      serverListening = false;
    }
  }
#endif

if (!serverListening) {
  //hey, I'm walkin over here
}

Now on Windows we try to create our very own mutex. If that succeeds, all is normal. If that returns an error, we simply close our server because we know some other instance owns the mutex.

Not ideal but it covers single-instance scenario reasonably well.

If you want to use this in application, you can download the example and use it as follows:

if (!SingleInstance::attach()) {
  return static_cast<int>(0x80004004); //exit immediately if another instance is running
}

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.