lzon.ca

How to make a single instance program in C++

Posted May 02, 2026 3 min read

I just discovered a neat trick for enforcing a single instance of a C++ program.


It’s just a small and stateless function that uses UNIX sockets.

bool processAlreadyExists()
{
    int fd = socket(AF_UNIX, SOCK_STREAM, 0);

    sockaddr_un addr;
    memset(&addr, 0, sizeof(addr));
    addr.sun_family = AF_UNIX;

    // make socket 'abstract' by setting the first char of the name to '\0'
    string socket_name = " jot_lock";
    socket_name[0] = '\0';

    memcpy(addr.sun_path, socket_name.data(), socket_name.size());

    if (bind(fd, (sockaddr*)&addr, sizeof(addr)) == -1)
    {
        // bind fails, return true
        // means a first instance has already started
        return true;
    }

    // bind succeeds, return false
    // this is the first instance
    return false;
}

And here’s a small program that demonstrates how to use it.

//
// *nix
//
#include <sys/socket.h>
#include <sys/un.h>

//
// std
//
#include <string>
#include <iostream>
using namespace std;

bool processAlreadyExists()
{
    int fd = socket(AF_UNIX, SOCK_STREAM, 0);

    sockaddr_un addr;
    memset(&addr, 0, sizeof(addr));
    addr.sun_family = AF_UNIX;

    // make socket 'abstract' by setting the first char of the name to '\0'
    string socket_name = " jot_lock";
    socket_name[0] = '\0';

    memcpy(addr.sun_path, socket_name.data(), socket_name.size());

    if (bind(fd, (sockaddr*)&addr, sizeof(addr)) == -1)
    {
        // bind fails, return true
        // means a first instance has already started
        return true;
    }

    // bind succeeds, return false
    // this is the first instance
    return false;
}

int main()
{
    if (processAlreadyExists())
    {
        cout << "second process, exiting now..." << endl;
        return EXIT_SUCCESS;
    }

    cout << "first process, exiting in 5 seconds..." << endl;
    sleep(5);

    return EXIT_SUCCESS;
}

It works perfectly on Linux, leveraging a unique feature called Abstract Sockets. When a UNIX socket is given a name beginning with a zero ('\0' , not '0'), it is considered Abstract. That means the system will not create a file for the socket in the file system, which is the default behaviour. The following is the relevant exert from the documentation.

an abstract socket address is distinguished (from a pathname socket) by the fact that sun_path[0] is a null byte (‘\0’). The socket’s address in this namespace is given by the additional bytes in sun_path that are covered by the specified length of the address structure. (Null bytes in the name have no special significance.) The name has no connection with filesystem pathnames. When the address of an abstract socket is returned, the returned addrlen is greater than sizeof(sa_family_t) (i.e., greater than 2), and the name of the socket is contained in the first (addrlen - sizeof(sa_family_t)) bytes of sun_path.

This means that the socket ceases to exist entirely at the end of the process that created it. That’s important because otherwise you’d need to care about whether a dangling socket file was leftover by a previous process. With abstract sockets the system will do all the cleanup for you, no matter what.

I’m using this trick now in an old project that I picked up after letting it sit for several months. It’s called ‘jot’, a small program that creates virtual key presses. I use it now just to type out date codes like the ones in this post.


I love discovering little tricks like this. If you have any of your own, let me know!

Email me at mail@lzon.ca, or reach out through one of my social accounts linked on the homepage.

Settings

Theme

Primary
Secondary
Tertiary