Hi, what is the best and fail-safe way to detect whether the running program is an unique instance or not on Unix? I prefer not using DBus because (1) I'm not used to DBus myself (2) cannot find any easily portable simple example.
So far I've found the following strategies:
-
Creating a file: This crate provides an easy to use API to automate the process of detecting uniqueness. The idea is that if I can create a file in RAMDisk (for example,
$XDG_RUNTIME_DIR
or/dev/shm
) when the app is first run, all other instances can check if that file exists to determine if the program is unique. Problem with this approach is that I don't know if the file is going to be deleted if the application is terminated unexpectedly. -
Via TCP sockets: This example demonstrates uniqueness detection by binding a TCP port. It has the same problem of not being able to "un-bind" the port if the app terminates forcefully.
-
Linux Abstract Sockets: This article demonstrates a really easy way to detect uniqueness but it also has some caveats as stated in the article, one of which can pose security risk (even though it's not a big problem for the project I'm working on).
What is the industry standard way to approach application uniqueness in POSIX (or even just Linux)? Is DBus the only way?
Update, I just went with Linux Abstract Sockets. Easy to understand and the possible security risks are not fatal for the project I'm working on.
use nix::sys::socket::AddressFamily;
use nix::sys::socket::SockAddr;
use nix::sys::socket::SockFlag;
use nix::sys::socket::SockType;
use nix::sys::socket::UnixAddr;
use nix::sys::socket::bind;
use nix::sys::socket::socket;
pub fn is_unique() -> Result<bool, Box<dyn std::error::Error>> {
let socket = socket(AddressFamily::Unix, SockType::Stream, SockFlag::empty(), None)?;
let addr = SockAddr::Unix(UnixAddr::new_abstract(crate::consts::APP_ID.as_bytes())?);
match bind(socket, &addr) {
Err(e) => match e {
nix::Error::Sys(nix::errno::Errno::EADDRINUSE) => Ok(false),
_ => Err(Box::new(e))
},
_ => Ok(true)
}
}