fork
fork copied to clipboard
Question, which library should I use to fork
Hello, I are using nix and fork crate in my program. Today I found that a fork function is also provided in nix crate, but use unsafe, and the fork method of the fork` crate does not need to use unsafe.
If possible, I want the program to rely on fewer libraries, and I am a rtest novice. Does this mean that the implementation of fork crate is relatively secure and has less restrictions (println! cannot be used in the subprocesses of fork in nix crate!). Should I keep the fork crate. Thanks
use nix::{sys::wait::waitpid,unistd::{fork, ForkResult, write}};
match unsafe{fork()} {
Ok(ForkResult::Parent { child, .. }) => {
println!("Continuing execution in parent process, new child has pid: {}", child);
waitpid(child, None).unwrap();
}
Ok(ForkResult::Child) => {
// Unsafe to use `println!` (or `unwrap`) here. See Safety.
write(libc::STDOUT_FILENO, "I'm a new child process\n".as_bytes()).ok();
unsafe { libc::_exit(0) };
}
Err(_) => println!("Fork failed"),
}
It depends on your use case, maybe the fork crate works maybe not, but in any case, when using libc you will probably always will be using unsafe
nix crate is providing a wrapper for libc::fork():
pub unsafe fn fork() -> Result<ForkResult> {
use self::ForkResult::*;
let res = unsafe { libc::fork() };
Errno::result(res).map(|res| match res {
0 => Child,
res => Parent { child: Pid(res) },
})
}
Which is very similar to what immortal/fork provides (although I'd argue that nix is doing a better job):
https://github.com/immortal/fork/blob/b3229f8e5ec1b7d79e43f69f45ee8a56cbc432bd/src/lib.rs#L113-L120
The Parent wraps the PID value directly:
https://github.com/immortal/fork/blob/b3229f8e5ec1b7d79e43f69f45ee8a56cbc432bd/src/lib.rs#L19-L23
With nix you get Pid which is a bit more useful.
Additionally, nix fork call returns proper error for you. If the fork fails you get -1 from libc::fork(), but need to look up the associated errno via a separate call that you may not be aware of. immortal/fork is returning -1 while nix fork will handle that for you which is a bit more helpful.
Likewise look at the immortal/fork docs which refer to the nix fork about safety, as it looks like nix is warning you more correctly with the unsafe, while immortal/fork is hiding that? (not sure if that means the same issues can occur, but perhaps due to the docs reference it can?)
Thus I don't know if you should compare them like that to infer that immortal/fork is safer than nix fork, you could make your own wrapper to the unsafe nix call to treat it as safe too if that were just the case.
I am responding here mostly because I was a bit curious why the direct libc calls for logic that isn't implemented as well as nix? Wouldn't it be better to leverage the nix calls and structs for that same functionality?
Likewise for daemon call, it's implemented it more in rust than using the equivalent libc call that nix wraps. From what I've read though there isn't meant to be a double fork there usually, and you'll notice in glibc that's not the case but it's also not standardized so I guess it's up to you 🤷♂️