Skip to main content

fresh/server/daemon/
mod.rs

1//! Daemonization support for running the server in the background
2//!
3//! On Unix: Uses double-fork with setsid() to fully detach from terminal
4//! On Windows: Uses CreateProcess with DETACHED_PROCESS flag
5
6use std::io;
7use std::path::PathBuf;
8
9#[cfg(unix)]
10mod unix;
11#[cfg(windows)]
12mod windows;
13
14#[cfg(unix)]
15pub use unix::*;
16#[cfg(windows)]
17pub use windows::*;
18
19/// Write the server PID to a file for tracking
20pub fn write_pid_file(socket_dir: &std::path::Path, session_id: &str) -> io::Result<PathBuf> {
21    let pid_file = socket_dir.join(format!("{}.pid", session_id));
22    std::fs::write(&pid_file, std::process::id().to_string())?;
23    Ok(pid_file)
24}
25
26/// Read the server PID from a file
27pub fn read_pid_file(socket_dir: &std::path::Path, session_id: &str) -> io::Result<Option<u32>> {
28    let pid_file = socket_dir.join(format!("{}.pid", session_id));
29    if !pid_file.exists() {
30        return Ok(None);
31    }
32
33    let content = std::fs::read_to_string(&pid_file)?;
34    content
35        .trim()
36        .parse()
37        .map(Some)
38        .map_err(|e| io::Error::other(format!("Invalid PID file: {}", e)))
39}
40
41#[cfg(test)]
42mod tests {
43    use super::*;
44
45    #[test]
46    fn test_is_process_running() {
47        // Current process should be running
48        let pid = std::process::id();
49        assert!(is_process_running(pid));
50
51        // PID 999999999 is unlikely to exist
52        assert!(!is_process_running(999999999));
53    }
54}