Skip to content

jamesgober/proc-daemon

Repository files navigation

High-Performance Process EcoSystem for Rust

Process Daemon
RUST DAEMON FRAMEWORK

Crates.io   Crates.io Downloads   License   docs.rs   GitHub CI

A foundational framework for building high-performance, resilient daemon services in Rust. Designed for enterprise applications requiring nanosecond-level performance, bulletproof reliability, and extreme concurrency.

Status

✅ v1.0.0 Stable Release — Production-ready with zero critical vulnerabilities, comprehensive testing (46/46 tests passing), and cross-platform validation. See release notes for details.

Features

Core Capabilities

  • Zero-Copy Architecture: Minimal allocations with memory pooling for maximum performance
  • Runtime Agnostic: First-class support for both Tokio and async-std via feature flags
  • Cross-Platform: Native support for Linux, macOS, and Windows with platform-specific optimizations
  • Graceful Shutdown: Coordinated shutdown with configurable timeouts and subsystem awareness
  • Signal Handling: Robust cross-platform signal management (SIGTERM, SIGINT, SIGQUIT, SIGHUP, Windows console events)

Advanced Features

  • Subsystem Management: Concurrent subsystem lifecycle management with health checks and auto-restart
  • Configuration Hot-Reload: Dynamic configuration updates without service interruption
  • Structured Logging: High-performance tracing with JSON support and log rotation
  • Metrics Collection: Built-in performance monitoring and resource tracking
  • Memory Safety: Safe Rust by default (#![deny(unsafe_code)]); Windows monitoring uses guarded unsafe when the windows-monitoring feature is enabled

Enterprise Ready

  • High Concurrency: Built for 100,000+ concurrent operations
  • Resource Management: Intelligent memory pooling and NUMA awareness
  • Health Monitoring: Comprehensive subsystem health checks and diagnostics
  • Production Tested: Battle-tested patterns from high-scale deployments



Installation

Add this to your Cargo.toml:

[dependencies]
proc-daemon = "1.0.0"

# Optional features
proc-daemon = { version = "1.0.0", features = ["full"] }

Rust Version: Requires Rust 1.82.0 or later

Feature Flags

Feature Description Default
tokio Tokio runtime support
async-std async-std runtime support (unmaintained; best-effort legacy)
metrics Performance metrics collection and introspection
console Enhanced console output
json-logs JSON structured logging
config-watch Configuration hot-reloading
mmap-config Memory-mapped config file loading (TOML fast-path, safe fallback)
mimalloc Use mimalloc as global allocator
high-res-timing High-resolution timing via quanta
scheduler-hints Enable scheduler tuning hooks (no-op by default)
scheduler-hints-unix Best-effort Unix niceness adjustment (uses renice; no-op without privileges)
lockfree-coordination Lock-free coordination/events via crossbeam-channel
profiling Optional CPU profiling via pprof (Unix-preferred; Windows build issues)
heap-profiling Optional heap profiling via dhat
full All features enabled

Note: async-std is discontinued upstream; support here is best-effort and intended for existing users. pprof has known Windows build incompatibilities; users on Windows can use other profiling tools or enable on Unix systems.

Quick Start

Simple Daemon

use proc_daemon::{Daemon, Config};
use std::time::Duration;

async fn my_service(mut shutdown: proc_daemon::ShutdownHandle) -> proc_daemon::Result<()> {
    let mut counter = 0;
    
    loop {
        tokio::select! {
            _ = shutdown.cancelled() => {
                tracing::info!("Service shutting down gracefully after {} iterations", counter);
                break;
            }
            _ = tokio::time::sleep(Duration::from_secs(1)) => {
                counter += 1;
                tracing::info!("Service running: iteration {}", counter);
            }
        }
    }
    
    Ok(())
}

#[tokio::main]
async fn main() -> proc_daemon::Result<()> {
    let config = Config::new()?;
    
    Daemon::builder(config)
        .with_task("my_service", my_service)
        .run()
        .await
}

High-Resolution Timing (optional)

Enable the high-res-timing feature to access a fast, monotonic clock backed by quanta:

[dependencies]
proc-daemon = { version = "1.0.0", features = ["high-res-timing"] }
#[cfg(feature = "high-res-timing")]
{
    let t0 = proc_daemon::timing::now();
    // ... work ...
    let t1 = proc_daemon::timing::now();
    let dt = t1.duration_since(t0);
    println!("elapsed: {:?}", dt);
}

Mimalloc Global Allocator (optional)

Enable the mimalloc feature to switch the global allocator for potential performance wins in allocation-heavy workloads:

[dependencies]
proc-daemon = { version = "1.0.0", features = ["mimalloc"] }

No code changes are required—proc-daemon sets the global allocator when the feature is enabled.

Lock-free Coordination (optional)

Enable the lockfree-coordination feature to use a lock-free MPMC channel for coordination. This exposes a small channel facade and optional subsystem events for state changes.

[dependencies]
proc-daemon = { version = "1.0.0", features = ["lockfree-coordination"] }

APIs:

  • proc_daemon::coord::chan::{unbounded, try_recv} — Uniform API over crossbeam-channel (enabled) or std::sync::mpsc (fallback).
  • SubsystemManager::enable_events() and SubsystemManager::try_next_event() — non-blocking event polling.
  • SubsystemManager::subscribe_events() — get a Receiver<SubsystemEvent> to poll from another task when events are enabled.

Event type:

SubsystemEvent::StateChanged { id, name, state, at }

Multi-Subsystem Daemon

use proc_daemon::{Daemon, Config, Subsystem, ShutdownHandle, RestartPolicy};
use std::pin::Pin;
use std::future::Future;
use std::time::Duration;

// Define a custom subsystem
struct HttpServer {
    port: u16,
}

impl Subsystem for HttpServer {
    fn run(&self, mut shutdown: ShutdownHandle) -> Pin<Box<dyn Future<Output = proc_daemon::Result<()>> + Send>> {
        let port = self.port;
        Box::pin(async move {
            tracing::info!("HTTP server starting on port {}", port);
            
            loop {
                tokio::select! {
                    _ = shutdown.cancelled() => {
                        tracing::info!("HTTP server shutting down");
                        break;
                    }
                    _ = tokio::time::sleep(Duration::from_millis(100)) => {
                        // Handle HTTP requests here
                    }
                }
            }
            
            Ok(())
        })
    }

    fn name(&self) -> &str {
        "http_server"
    }

    fn restart_policy(&self) -> RestartPolicy {
        RestartPolicy::ExponentialBackoff {
            initial_delay: Duration::from_secs(1),
            max_delay: Duration::from_secs(60),
            max_attempts: 5,
        }
    }
}

async fn background_worker(mut shutdown: ShutdownHandle) -> proc_daemon::Result<()> {
    while !shutdown.is_shutdown() {
        tokio::select! {
            _ = shutdown.cancelled() => break,
            _ = tokio::time::sleep(Duration::from_secs(5)) => {
                tracing::info!("Background work completed");
            }
        }
    }
    Ok(())
}

#[tokio::main]
async fn main() -> proc_daemon::Result<()> {
    let config = Config::builder()
        .name("multi-subsystem-daemon")
        .shutdown_timeout(Duration::from_secs(30))
        .worker_threads(4)
        .build()?;

    Daemon::builder(config)
        .with_subsystem(HttpServer { port: 8080 })
        .with_task("background_worker", background_worker)
        .run()
        .await
}

Configuration

Programmatic Configuration

use proc_daemon::{Config, LogLevel};
use std::time::Duration;

let config = Config::builder()
    .name("my-daemon")
    .log_level(LogLevel::Info)
    .json_logging(true)
    .shutdown_timeout(Duration::from_secs(30))
    .worker_threads(8)
    .enable_metrics(true)
    .hot_reload(true)
    .build()?;

File Configuration (TOML)

Create a daemon.toml file:

name = "my-production-daemon"

[logging]
level = "info"
json = false
color = true
file = "/var/log/my-daemon.log"

[shutdown]
timeout_ms = 30000
force_timeout_ms = 45000
kill_timeout_ms = 60000

[performance]
worker_threads = 0  # auto-detect
thread_pinning = false
memory_pool_size = 1048576
numa_aware = false
lock_free = true

[monitoring]
enable_metrics = true
metrics_interval_ms = 1000
health_checks = true

Load the configuration:

let config = Config::load_from_file("daemon.toml")?;

Environment Variables

All configuration options can be overridden with environment variables using the DAEMON_ prefix:

export DAEMON_NAME="env-daemon"
export DAEMON_LOGGING_LEVEL="debug"
export DAEMON_SHUTDOWN_TIMEOUT_MS="60000"
export DAEMON_PERFORMANCE_WORKER_THREADS="16"

Advanced Usage

Custom Subsystems with Health Checks

struct DatabasePool {
    connections: Arc<AtomicUsize>,
}

impl Subsystem for DatabasePool {
    fn run(&self, mut shutdown: ShutdownHandle) -> Pin<Box<dyn Future<Output = proc_daemon::Result<()>> + Send>> {
        let connections = Arc::clone(&self.connections);
        Box::pin(async move {
            // Database pool management logic
            Ok(())
        })
    }

    fn name(&self) -> &str {
        "database_pool"
    }

    fn health_check(&self) -> Option<Box<dyn Fn() -> bool + Send + Sync>> {
        let connections = Arc::clone(&self.connections);
        Some(Box::new(move || {
            connections.load(Ordering::Acquire) > 0
        }))
    }
}

Metrics Collection

#[cfg(feature = "metrics")]
use proc_daemon::metrics::MetricsCollector;

let collector = MetricsCollector::new();

// Increment counters
collector.increment_counter("requests_total", 1);

// Set gauge values
collector.set_gauge("active_connections", 42);

// Record timing histograms
collector.record_histogram("request_duration", Duration::from_millis(150));

// Get metrics snapshot
let snapshot = collector.get_metrics();
println!("Uptime: {:?}", snapshot.uptime);

Signal Handling Configuration

use proc_daemon::signal::SignalConfig;

let signal_config = SignalConfig::new()
    .with_sighup()  // Enable SIGHUP handling
    .without_sigint()  // Disable SIGINT
    .with_custom_handler(12, "Custom signal");

Daemon::builder(config)
    .with_signal_config(signal_config)
    .run()
    .await

Architecture

Zero-Copy Design

proc-daemon is built around zero-copy principles:

  • Arc-based sharing: Configuration and state shared via Arc to avoid cloning
  • Lock-free coordination: Uses atomic operations and lock-free data structures
  • Memory pooling: Pre-allocated memory pools for high-frequency operations
  • Efficient serialization: Direct memory mapping for configuration loading

Subsystem Lifecycle

graph TD
    A[Register] --> B[Starting]
    B --> C[Running]
    C --> D[Health Check]
    D --> C
    C --> E[Stopping]
    E --> F[Stopped]
    F --> G[Restart?]
    G -->|Yes| B
    G -->|No| H[Removed]
    C --> I[Failed]
    I --> G
Loading

Shutdown Coordination

proc-daemon implements a sophisticated shutdown coordination system:

  1. Signal Reception: Cross-platform signal handling
  2. Graceful Notification: All subsystems notified simultaneously
  3. Coordinated Shutdown: Subsystems shut down in dependency order
  4. Timeout Management: Configurable graceful and force timeouts
  5. Resource Cleanup: Automatic cleanup of resources and handles

Testing

Run the test suite:

# Run all tests
cargo test

# Run tests with all features
cargo test --all-features

# Run integration tests
cargo test --test integration

# Run benchmarks
cargo bench


Hot-Reload (optional)

Enable config-watch to live-reload daemon.toml at runtime (optionally combine with mmap-config for fast TOML loading). The daemon maintains a live snapshot accessible via Daemon::config_snapshot().

Run the example:

cargo run --example hot_reload --features "tokio config-watch toml mmap-config"

Notes:

  • Place daemon.toml in the working directory.
  • The watcher starts automatically when Config.hot_reload = true.


Examples

All runnable examples are available in the examples/ directory. Here are the key ones:

simple.rs

A minimal daemon that demonstrates basic setup and graceful shutdown:

cargo run --example simple --features tokio

comprehensive.rs

Multi-subsystem daemon showcasing:

  • Custom subsystem implementations
  • Health checks
  • Restart policies
  • Metrics collection
cargo run --example comprehensive --features tokio,metrics

hot_reload.rs

Configuration hot-reload demonstration that watches daemon.toml:

cargo run --example hot_reload --features "tokio config-watch toml mmap-config"

Edit daemon.toml to see the daemon pick up changes without restart.

metrics_server.rs

Metrics collection and introspection example:

cargo run --example metrics_server --features "tokio metrics"


PERFORMANCE

proc-daemon is designed for extreme performance:

Running Benchmarks

cargo bench

Typical performance:

  • Daemon Creation: ~1-5μs
  • Subsystem Registration: ~500ns per subsystem
  • Shutdown Coordination: ~10-50μs for 100 subsystems
  • Signal Handling: ~100ns latency
  • Metrics Collection: ~10ns per operation

Memory Usage

  • Base daemon: ~1-2MB
  • Per subsystem: ~4-8KB
  • Configuration: ~1-4KB
  • Signal handling: ~512B


🔗 See PERFORMANCE.md for up-to-date benchmarks, metrics, and version-over-version improvements.




Security

v1.0.0 Security Posture

  • Zero Critical Vulnerabilities: All dependencies audited and patched
  • Bytes Overflow Fixed: CVE-level integer overflow in BytesMut::reserve patched (bytes 1.11.1+)
  • Optional Feature Auditing: Unmaintained dependencies (async-std, instant) allowlisted and documented
  • Memory Safety: Safe Rust by default (#![deny(unsafe_code)]); Windows monitoring uses guarded unsafe only when explicitly enabled
  • Signal Safety: Async signal handling prevents race conditions and signal-induced deadlocks
  • Resource Limits: Configurable limits prevent resource exhaustion attacks
  • Graceful Degradation: Continues operating even when subsystems fail

Running Security Checks

# Verify no unallowed vulnerabilities
cargo audit

# Static analysis
cargo clippy --all-features --all-targets -- -D warnings

# Check for unsafe code
cargo unsafe-all-targets

See .cargo/audit.toml for documented allowed vs. disallowed vulnerabilities.

Development Setup

git clone https://github.com/jamesgober/proc-daemon.git
cd proc-daemon

# Build with all features enabled
cargo build --all-features

# Run all tests
cargo test --all-features

# Run linting checks
cargo clippy --all-features --all-targets -- -D warnings

# Run benchmarks
cargo bench

# Check security vulnerabilities
cargo audit

Supported Platforms

  • Linux: Full support, optimized for production
  • macOS: Full support, verified on x86_64 and ARM64
  • Windows: Supported, with caveats listed below
  • FreeBSD: Likely works but not regularly tested

Windows Note: Some optional features (pprof, renice-based scheduler hints) have Unix-specific dependencies. These features gracefully disable on Windows with working alternatives or no-ops suitable for development.



Documentation:



Acknowledgments

  • Inspired by production daemon patterns from high-scale deployments
  • Built on the excellent Rust async ecosystem (Tokio; async-std legacy support)
  • Configuration management powered by Figment
  • Logging via the tracing ecosystem



DEVELOPMENT & CONTRIBUTION

We welcome contributions! Please see CONTRIBUTING.md for guidelines.




Rust Logo
Built with Rust.


⚖️ License

Licensed under the Apache License, version 2.0 (the "License"); you may not use this software, including, but not limited to the source code, media files, ideas, techniques, or any other associated property or concept belonging to, associated with, or otherwise packaged with this software except in compliance with the License.

You may obtain a copy of the License at: http://www.apache.org/licenses/LICENSE-2.0.

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

See the LICENSE file included with this project for the specific language governing permissions and limitations under the License.


COPYRIGHT © 2026 JAMES GOBER.

About

A high-performance, cross-platform daemon framework for Rust. Built with an async-native architecture and robust graceful shutdown for creating resilient, production-grade services.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors