Search code examples
rustmutex

Single instance verification error in Rust


I am looking for a solution to verify that the instance of my program is unique. I have restricted access to the IO, which I need to limit as much as possible, so the mutex solution seemed the most suitable for my situation So I have chosen the option of creating a mutex via the minwin crate.

The problem is that when I try to run 2 instances of the program it doesn't seem to detect the lock.

Here's the code:

use minwin::{sync::Mutex, named::CreateNamedError};
use std::{process, sync::Once};

static mut UNIQUE_MUTEX: Option<Mutex> = None;
static INIT: Once = Once::new();

fn initialize_mutex() {
    const MUTEX_NAME: &str = "test";
    unsafe {
        UNIQUE_MUTEX = match Mutex::create_named(MUTEX_NAME) {
            Ok(mutex) | Err(CreateNamedError::AlreadyExists(mutex)) => Some(mutex),
            Err(_) => {
                process::exit(1);
            }
        };
    }
}

pub fn set_unique_instance() -> bool {
    INIT.call_once(|| {
        initialize_mutex();
    });

    let mutex_ref = unsafe {
        UNIQUE_MUTEX.as_ref().unwrap()
    };

    match mutex_ref.try_lock() {
        Ok(_) => true,
        Err(_) => false,
    }
}

pub fn unlock() {
    let mutex_ref = unsafe {
        UNIQUE_MUTEX.as_ref().unwrap()
    };
    drop(mutex_ref.lock().unwrap());
}

fn main() {
    if set_unique_instance() {
        loop {
            println!("It's the first instance");
        }
    } else {
        println!("Another instance is already running.");
    }
}

Here is my cargo.toml file :

[package]
name = "zkclientt"
version = "0.1.0"
edition = "2021"

[dependencies]
minwin = { git = "https://github.com/Jascha-N/minwin-rs", version = "0.1.0" }

The two instances of my program continually enter "It's the first instance". Can you show me how to resolve this error?


Solution

  • You can use the library named-lock = "0.3.0" which is cross platform

    use named_lock::{Error, NamedLock};
    use named_lock::NamedLockGuard;
    
    fn main() {
        let lock = NamedLock::create("my_lock").unwrap();
        match lock.try_lock() {
            Ok(NamedLockGuard { .. }) => {
                loop {
                    println!("It's the first instance");
                }
            }
            Err(Error::WouldBlock) => {
                println!("Another instance is already running.");
            }
            _ => {
                println!("Another error.");
            }
    
        };
    }