Rust: Implement a way to daemonize a process

Created on 13 Jul 2014  路  14Comments  路  Source: rust-lang/rust

Being able to daemonize is a common thing for applications to do. There should be something in Rust similar to the C daemon function: http://man7.org/linux/man-pages/man3/daemon.3.html

Most helpful comment

use std::process::Command;
use std::env;

fn main() {
    let args: Vec<String> = env::args().collect();
    if args.len() == 2 {
        if &args[1] == "start" {
                let child = Command::new(&args[0])
                                    .spawn().expect("Child process failed to start.");
                println!("child pid: {}", child.id());
                // child.forget() No Child Left Behind
        }
    } else {
        println!("This is an incredibly simple daemon!");
    }
}

This works for me.

All 14 comments

Could you elaborate a little more on what you'd like here? It looks like the C daemon function can be built on top of what we already provide today, and we also have some additional facilities with Process and Command

Hey Alex, I asked on the mailing list and IRC on how to do this, and I didn't get any responses, so I assumed it wasn't possible. Can you explain how I can achieve the same functionality as the C daemon function in Rust?

You'll want to spawn a new process with the detached option set to true, like so:

use std::io::Command;
use std::os;

fn main() {
    let args = os::args();
    if args.len() == 1 {
        let child = Command::new(args.get(0).as_slice())
                            .arg("child")
                            .detached().spawn().unwrap();
        println!("child: {}", child.id());
        child.forget();
    } else {
        println!("I'm a daemon!");
    }
}

This is all possible today, so I'm going to close this issue.

So if I understand correctly, if I run this code with no arguments, I should see the process ID of the daemon and the daemon should print "I'm a daemon"? Because I only see the child process ID printed.

I believe that is because the child has been detached so it did not inherit the same stdio file descriptors.

I also added a 60 second sleep call after the "I'm a daemon!" println and ran pgrep and ps -p with the child process ID. It doesn't seem like the daemon is running.

Ah, that's because the stdout handle is closed so the call to println! is failing the rust task (discoverable through strace)

Since std::io::Command is now defunct would someone be able to post a working example using std::process similar to the one that @alexcrichton posted above?

use std::process::Command;
use std::env;

fn main() {
    let args: Vec<String> = env::args().collect();
    if args.len() == 2 {
        if &args[1] == "start" {
                let child = Command::new(&args[0])
                                    .spawn().expect("Child process failed to start.");
                println!("child pid: {}", child.id());
                // child.forget() No Child Left Behind
        }
    } else {
        println!("This is an incredibly simple daemon!");
    }
}

This works for me.

@somedude232 thanks

The code above is not an acceptable solution, it's a backdoor. If anyone has copied the code above into a suid program, privilege escalation is trivial, since the args array is set by the calling process and args[0] cannot be trusted. Even if that wasn't true, a race condition would still exist since the path args[0] names could be replaced before the Command is executed.

@Ofenhed do you have a safer alternative?

The correct way would be to demonize the actual running process. I haven't tried it, but running the unsafe libc functions fork (and killing the parent) and setsid may do the trick.

To slightly increase security with the examples above on systems with /proc available, args[0] could be replaced with "/proc/self/exe".

@alexcrichton Could we possibly reopen this thread (as it is not solved) or at least remove the backdoors as recommended solutions?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

modsec picture modsec  路  3Comments

tikue picture tikue  路  3Comments

drewcrawford picture drewcrawford  路  3Comments

SharplEr picture SharplEr  路  3Comments

behnam picture behnam  路  3Comments