MiddleCodeOccasionalNot answered yet
Write a cross-platform program that ensures only one instance runs.
Write a cross-platform single-instance guard: when a second copy of the program starts while one is already running, the second must detect it and exit.
Constraints:
- On POSIX use an atomic file lock (avoid the TOCTOU race of reading a PID and checking liveness).
- On Windows use a named kernel object so the check works across processes.
- The lock/handle must be released automatically on exit, including normal termination.
class SingleInstance {
public:
explicit SingleInstance(const std::string& lock_path); // POSIX
~SingleInstance();
SingleInstance(const SingleInstance&) = delete;
// your code here
};
Write the implementation.
Two canonical approaches: on POSIX take an exclusive flock(LOCK_EX | LOCK_NB) on a PID file; on Windows create a named mutex via CreateMutex and check ERROR_ALREADY_EXISTS. Both release on exit.
- ✗Checking for a PID in the file and then testing if that process is alive — has a TOCTOU race; use a file lock instead, which is atomic
- ✗Not writing the current PID to the lock file — makes debugging harder; you can't tell which instance holds the lock
- ✗Forgetting to close the fd before exec() in a fork/exec model — the lock would be released; use O_CLOEXEC or fcntl(F_SETFD, FD_CLOEXEC)
- →How do you signal the already-running instance to bring its window to front on Windows?
- →What happens to the file lock if the process is killed with SIGKILL?
Contents
Single Instance Program
POSIX (Linux/macOS)
#include <fcntl.h>
#include <sys/file.h>
#include <unistd.h>
#include <cstdio>
#include <cstdlib>
#include <string>
class SingleInstance {
public:
explicit SingleInstance(const std::string& lock_path) : path_(lock_path) {
fd_ = ::open(path_.c_str(), O_CREAT | O_RDWR | O_CLOEXEC, 0644);
if (fd_ < 0) { perror("open"); std::exit(1); }
if (::flock(fd_, LOCK_EX | LOCK_NB) != 0) {
std::fprintf(stderr, "Another instance is already running.\n");
::close(fd_);
std::exit(1);
}
::ftruncate(fd_, 0);
char buf[32];
int n = std::snprintf(buf, sizeof(buf), "%d\n", (int)::getpid());
::write(fd_, buf, n);
}
~SingleInstance() { ::flock(fd_, LOCK_UN); ::close(fd_); }
SingleInstance(const SingleInstance&) = delete;
private:
std::string path_;
int fd_ = -1;
};
int main() {
SingleInstance guard("/tmp/myapp.lock");
std::printf("Running as PID %d\n", (int)::getpid());
}
Windows
#ifdef _WIN32
#include <windows.h>
class SingleInstance {
public:
explicit SingleInstance(const wchar_t* mutex_name) {
handle_ = ::CreateMutexW(nullptr, TRUE, mutex_name);
if (!handle_ || ::GetLastError() == ERROR_ALREADY_EXISTS) {
if (handle_) ::CloseHandle(handle_);
std::exit(1);
}
}
~SingleInstance() { if (handle_) { ::ReleaseMutex(handle_); ::CloseHandle(handle_); } }
SingleInstance(const SingleInstance&) = delete;
private:
HANDLE handle_ = nullptr;
};
#endifContents