# No-Mistakes Daemon Singleton Lock Mechanism and Process Management Strategy

> Learn the no-mistakes daemon singleton lock mechanism using OS-level file locks to prevent duplicate daemons. Discover this robust process management strategy.

- Repository: [Kun Chen/no-mistakes](https://github.com/kunchenguid/no-mistakes)
- Tags: deep-dive
- Published: 2026-07-25

---

**The no-mistakes daemon enforces a singleton instance per application home through an exclusive OS-level file lock on `<NM_HOME>/daemon.lock`, acquiring the lock before any IPC setup and releasing it automatically on process termination to prevent duplicate daemons.**

The `no-mistakes` daemon ensures only one instance runs per `NM_HOME` directory through a robust **singleton lock mechanism** and comprehensive process management strategy. This design prevents race conditions and orphaned processes in concurrent environments by leveraging kernel-managed file locks that automatically release when the process exits.

## How the Singleton Lock Works

The daemon implements mutual exclusion through an **exclusive file lock** that guarantees only one process can operate on a given application home at any time.

### Cross-Platform Lock Implementation

The lock abstraction resides in [`internal/daemon/lock.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/daemon/lock.go), with platform-specific implementations in [`internal/daemon/lock_unix.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/daemon/lock_unix.go) and [`internal/daemon/lock_windows.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/daemon/lock_windows.go).

On Unix systems, the implementation uses `syscall.Flock` with `LOCK_EX|LOCK_NB` flags to attempt a non-blocking exclusive lock:

```go
// Inside internal/daemon/lock_unix.go
func tryLockFile(f *os.File) error {
    // Non-blocking exclusive flock; returns ErrWouldBlock if another
    // process already holds the lock.
    return syscall.Flock(int(f.Fd()), syscall.LOCK_EX|syscall.LOCK_NB)
}

```

On Windows, [`internal/daemon/lock_windows.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/daemon/lock_windows.go) implements the same guarantee using `CreateFile` with `FILE_FLAG_OVERLAPPED` combined with `LockFileEx` for exclusive access.

### Lock Acquisition Sequence

The lock acquisition occurs as the very first action in `daemon.RunWithOptions`, before any stale-run recovery, socket binding, or IPC setup. This ordering ensures that the **daemon.lock** file at `<NM_HOME>/daemon.lock` acts as the authoritative semaphore for daemon ownership.

If `tryLockFile` fails because another process holds the lock, the daemon aborts immediately with a clear error message indicating that another daemon is already running. This check happens in `daemon.Start` via the collision detection logic in [`internal/daemon/collision.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/daemon/collision.go).

## Process Management Strategy

The daemon's lifecycle management builds upon the singleton lock to ensure robust operation across startup, health monitoring, and shutdown phases.

### Startup and Collision Detection

When `daemon.Start` initializes, it follows a strict sequence defined in [`internal/daemon/daemon.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/daemon/daemon.go):

1. **Acquire the lock** via `tryLockFile` using non-blocking exclusive mode
2. **Initialize IPC** by creating the Unix socket or Windows named pipe only after lock acquisition
3. **Start the RPC server** to accept client connections

This sequence guarantees that no second daemon can bind to the same socket while the first daemon holds the lock. If a collision occurs, [`internal/daemon/collision.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/daemon/collision.go) logs the error and terminates the duplicate instance.

### Health Monitoring and Stale Recovery

The daemon implements a health-check loop that periodically verifies daemon liveness through `daemon.IsRunning`. This function attempts to dial the daemon's socket with a short timeout to confirm responsiveness.

If the health check fails, indicating a dead process, the recovery mechanism in [`internal/daemon/recover_servers_unix.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/daemon/recover_servers_unix.go) and [`internal/daemon/recover_servers_windows.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/daemon/recover_servers_windows.go) detects stale lock files and removes them before allowing a new daemon to start. This prevents "zombie" locks from blocking legitimate new instances when the previous process crashed without cleaning up.

### Graceful Shutdown and Signal Handling

Normal termination follows a clean shutdown sequence triggered by platform-specific signal handlers in [`internal/daemon/signals_unix.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/daemon/signals_unix.go) and [`internal/daemon/signals_windows.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/daemon/signals_windows.go). These handlers translate `SIGTERM`, `SIGINT`, and other OS signals into an orderly shutdown:

```go
// Graceful shutdown via signal handling (Unix)
func handleSignals(stop chan<- struct{}) {
    sigs := make(chan os.Signal, 1)
    signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
    go func() {
        <-sigs
        // Perform any cleanup then close the lock file
        stop <- struct{}{}
    }()
}

```

The shutdown sequence closes the IPC socket, releases the file lock, and removes the lock file. Because the kernel automatically releases the file lock if the process crashes or is killed, the singleton guarantee remains intact even during unexpected termination.

## Summary

- The **singleton lock** uses an exclusive OS-level file lock on `<NM_HOME>/daemon.lock` to ensure only one daemon instance runs per application home
- Lock acquisition occurs in `daemon.RunWithOptions` before any socket binding or IPC initialization
- Platform-specific implementations in [`internal/daemon/lock_unix.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/daemon/lock_unix.go) and [`lock_windows.go`](https://github.com/kunchenguid/no-mistakes/blob/main/lock_windows.go) provide cross-platform compatibility
- **Health checks** via `daemon.IsRunning` detect stale processes and trigger recovery mechanisms in [`recover_servers_unix.go`](https://github.com/kunchenguid/no-mistakes/blob/main/recover_servers_unix.go) and [`recover_servers_windows.go`](https://github.com/kunchenguid/no-mistakes/blob/main/recover_servers_windows.go)
- **Signal handlers** in [`signals_unix.go`](https://github.com/kunchenguid/no-mistakes/blob/main/signals_unix.go) and [`signals_windows.go`](https://github.com/kunchenguid/no-mistakes/blob/main/signals_windows.go) ensure graceful shutdown and lock release
- The kernel automatically releases the lock on process crash, preventing permanent deadlocks

## Frequently Asked Questions

### How does the no-mistakes daemon prevent multiple instances from running?

The daemon uses an **exclusive file lock** on `<NM_HOME>/daemon.lock` acquired through `tryLockFile` at startup. If another instance holds the lock, the new instance aborts immediately with a collision error from [`internal/daemon/collision.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/daemon/collision.go). This OS-level lock prevents race conditions between concurrent startup attempts.

### What happens to the lock if the daemon process crashes?

The kernel automatically releases the file lock when the process terminates, regardless of whether the shutdown is graceful or caused by a crash. This behavior ensures that a lingering lock always reflects a live daemon, and stale locks from dead processes cannot block new instances indefinitely.

### How does the daemon recover from stale lock files?

During startup, `daemon.Start` invokes recovery logic in [`internal/daemon/recover_servers_unix.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/daemon/recover_servers_unix.go) or [`internal/daemon/recover_servers_windows.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/daemon/recover_servers_windows.go) to detect stale locks. The daemon performs a health ping via `daemon.IsRunning` to verify if the locking process is alive. If the check fails, the daemon removes the stale lock file and proceeds with normal startup.

### Is the singleton lock mechanism portable across operating systems?

Yes, the daemon abstracts platform differences through [`internal/daemon/lock.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/daemon/lock.go). Unix systems use `syscall.Flock` with `LOCK_EX|LOCK_NB`, while Windows uses `LockFileEx` with `FILE_FLAG_OVERLAPPED`. Both implementations provide identical singleton guarantees, ensuring consistent behavior across Linux, macOS, and Windows environments.