Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

win-mutex

A simple wrapper for creating and locking Windows named system mutexes via the windows crate.

Features

  • Create global (machine-wide) or local (session-scoped) named mutexes
  • Acquire locks with an optional timeout
  • RAII-style WinSystemMutexGuard that automatically releases the mutex when dropped

Add win-mutex to your Cargo.toml:

[dependencies]
win-mutex = { git = "https://github.com/rgbav/win-mutex" }

A crate may be provided in the future.

Usage

Basic example

use win_mutex::{WinSystemMutex, MutexIdentifier, LockTimeout};
use std::time::Duration;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Create (or open) a global, machine-wide named mutex
    let mutex = WinSystemMutex::new(MutexIdentifier::Global("MyAppMutex".to_string()))?;

    // Try to acquire the lock, waiting up to 5 seconds
    let _guard = mutex.try_lock(LockTimeout::After(Duration::from_secs(5)))?;

    println!("Mutex acquired – only one instance can be here at a time.");

    // _guard is dropped here, automatically releasing the mutex
    Ok(())
}

Single-instance application

A common use-case is preventing multiple instances of an application from running at the same time:

use std::process::exit;
use std::time::Duration;
use win_mutex::{LockTimeout, WaitError, WinSystemMutex, MutexIdentifier};

fn main() {
    let mutex = WinSystemMutex::new(
        MutexIdentifier::Global("dcf25dfb-ed09-43a7-b3b5-83c0065e89f4".to_string())
    ).expect("Failed to create mutex");

    match mutex.try_lock(LockTimeout::After(Duration::from_secs(5))) {
        Ok(_guard) => {
            println!("Running as the only instance.");
            // ... application logic ...
        }
        Err(WaitError::Timeout) => {
            println!("Another instance is already running. Exiting.");
            exit(0);
        }
        Err(WaitError::Failed(code)) => {
            println!("Failed to acquire mutex (error code: {code}). Exiting.");
            exit(1);
        }
    }
}

Permissions & Global Mutexes

Using new_permissive

use win_mutex::{WinSystemMutex, MutexIdentifier};

// Elevated service or administrator process — creates the mutex
// with a NULL DACL so that standard-user processes can open it.
let mutex = WinSystemMutex::new_permissive(
    MutexIdentifier::Global("my-app-guid".to_string())
)?;

// Standard desktop application — opens the same mutex without needing
// elevated rights, because the NULL DACL permits all access.
let mutex = WinSystemMutex::new(
    MutexIdentifier::Global("my-app-guid".to_string())
)?;

Security note: A NULL DACL removes all access control from the kernel object. Only use new_permissive for coordination primitives (mutexes), not for objects that guard sensitive data.


Abandoned Mutexes

If a process terminates while holding the mutex (e.g. due to a panic or crash), Windows marks it as abandoned. The next caller of try_lock will still acquire the lock and receive Ok(guard) — the underlying WaitForSingleObject returns WAIT_ABANDONED in this case, which this crate treats as a successful acquisition.

This means you should always consider that the protected resource may be in an inconsistent state when taking over an abandoned mutex.


License

MIT – see LICENSE for details.

About

Wrapper to simplify windows system mutex access from the windows crate.

Topics

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Contributors

Languages