I've been trying to make a simple daemon in Rust that will listen to a port using tcp_stream and print the message. However, I'm running into two problems:
1) If my daemon uses println!, it crashes. If I remove all mentions of println!, the daemon works. How does stdout/stdin work when making a daemon?
One source I found on the Rust mailing list says "With modern init systems, such as systemd or launchctl, this works very nicely and application developer doesn't have to care about daemonisation and logging is also done simply via stdout." What do they mean by this?
2) When I run the code below in non-daemon mode, curls don't immediately return (running something like $ curl -XPOST localhost:9337 -d 'hi'
). I have to kill curl for the server to print something. Doesn't curl close the connection automatically? Shouldn't the sent bytes be available to the server after they are sent, not after the connection is closed?
extern crate getopts;
use getopts::{optflag,getopts};
use std::io::Command;
use std::io::net::tcp::{TcpListener};
use std::io::{Acceptor,Listener};
use std::os;
fn main() {
let args: Vec<String> = os::args();
let opts = [
optflag("d", "daemon", "conver this into a daemon"),
];
let matches = match getopts(args.tail(), opts) {
Ok(m) => { m },
Err(f) => { fail!(f.to_string()) }
};
// Create a daemon? if necessary
if matches.opt_present("d") {
let child = Command::new(args[0].as_slice())
.detached().spawn().unwrap();
println!("Created child: {}", child.id());
// Do I wrap this in unsafe?
child.forget();
return;
}
let listener = TcpListener::bind("127.0.0.1", 9337u16).ok().expect("Failed to bind");
let mut acceptor = listener.listen().ok().expect("Could not listen");
loop {
let mut tcp_stream = acceptor.accept().ok().expect("Could not accept connection");
println!("Accepted new connection");
let message = tcp_stream.read_to_string().unwrap();
println!("Received message {}", message);
}
}
smf_method(5)
. So when targeting other platforms than Linux and MacOS, daemonizing is still a thing. – Installation