Expand description
Library for creating a new process detached from the controlling terminal (daemon).
§Quick Start
use fork::{daemon, Fork};
use std::process::Command;
if let Ok(Fork::Child) = daemon(false, false) {
Command::new("sleep")
.arg("3")
.output()
.expect("failed to execute process");
}§Common Patterns
§Process Supervisor
Track multiple worker processes:
use fork::{fork, Fork, waitpid_nohang, WIFEXITED};
use std::collections::HashMap;
let mut workers = HashMap::new();
// Spawn 3 workers
for i in 0..3 {
match fork()? {
result @ Fork::Parent(_) => {
workers.insert(result, format!("worker-{}", i));
}
Fork::Child => {
// Do work...
std::thread::sleep(std::time::Duration::from_secs(5));
std::process::exit(0);
}
}
}
// Monitor workers without blocking
while !workers.is_empty() {
workers.retain(|child, name| {
match waitpid_nohang(child.child_pid().unwrap()) {
Ok(Some(status)) if WIFEXITED(status) => {
println!("{} exited", name);
false // Remove from map
}
_ => true // Keep in map
}
});
std::thread::sleep(std::time::Duration::from_millis(100));
}§Inter-Process Communication (IPC) via Pipe
use fork::{fork, Fork};
use std::io::{Read, Write};
use std::os::unix::io::FromRawFd;
// Create pipe before forking
let mut pipe_fds = [0i32; 2];
unsafe { libc::pipe(pipe_fds.as_mut_ptr()) };
match fork()? {
Fork::Parent(_child) => {
unsafe { libc::close(pipe_fds[1]) }; // Close write end
let mut reader = unsafe { std::fs::File::from_raw_fd(pipe_fds[0]) };
let mut msg = String::new();
reader.read_to_string(&mut msg)?;
println!("Received: {}", msg);
}
Fork::Child => {
unsafe { libc::close(pipe_fds[0]) }; // Close read end
let mut writer = unsafe { std::fs::File::from_raw_fd(pipe_fds[1]) };
writer.write_all(b"Hello from child!")?;
std::process::exit(0);
}
}§Daemon with PID File
use fork::{daemon, Fork, getpid};
use std::fs::File;
use std::io::Write;
if let Ok(Fork::Child) = daemon(false, false) {
// Write PID file
let pid = getpid();
let mut file = File::create("/var/run/myapp.pid")?;
writeln!(file, "{}", pid)?;
// Run daemon logic...
loop {
// Do work
std::thread::sleep(std::time::Duration::from_secs(60));
}
}§Safety and Best Practices
- Always check fork result - Functions marked
#[must_use]prevent accidents - Use
waitpid()- Reap child processes to avoid zombies - Prefer
redirect_stdio()- Safer thanclose_fd()for daemons - Fork early - Before creating threads, locks, or complex state
- Close unused file descriptors - Prevent resource leaks in children
- Handle signals properly - Consider what happens in both processes
§Platform Compatibility
This library uses POSIX system calls and is designed for Unix-like systems:
- Linux (all distributions)
- macOS (10.5+, replacement for deprecated
daemon(3)) - FreeBSD, OpenBSD, NetBSD
- Other POSIX-compliant systems
Windows is not supported as it lacks fork() system call.
Enums§
- Fork
- Fork result
Functions§
- WEXITSTATUS
- WIFEXITED
- WIFSIGNALED
- WTERMSIG
- chdir
- Change dir to
/see chdir(2) - close_
fd - Close file descriptors stdin, stdout, stderr
- daemon
- The daemon function is for programs wishing to detach themselves from the controlling terminal and run in the background as system daemons.
- fork
- Create a new child process see fork(2)
- getpgrp
- Get the process group ID of the current process see getpgrp(2)
- getpid
- Get the current process ID see getpid(2)
- getppid
- Get the parent process ID see getppid(2)
- redirect_
stdio - Redirect stdin, stdout, stderr to /dev/null
- setsid
- Create session and set process group ID see setsid(2)
- waitpid
- Wait for process to change status see wait(2)
- waitpid_
nohang - Wait for process to change status without blocking see wait(2)