From: Eugene Crosser Date: Mon, 3 Nov 2025 22:29:12 +0000 (+0100) Subject: Process requests in a separate process X-Git-Url: http://average.org/gitweb/?a=commitdiff_plain;h=HEAD;p=ironfinger.git Process requests in a separate process --- diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 0000000..94564f3 --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,8 @@ +[net] +offline = true + +[source] +[source.debian-packages] +directory = "/usr/share/cargo/registry" +[source.crates-io] +replace-with = "debian-packages" diff --git a/Cargo.toml b/Cargo.toml index 093e77c..d3d0934 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,3 +9,4 @@ path = "ironfinger.rs" [dependencies] getopts = "0.2" +libc = "0.2" diff --git a/ironfinger.rs b/ironfinger.rs index b22372b..0491334 100644 --- a/ironfinger.rs +++ b/ironfinger.rs @@ -1,36 +1,67 @@ use std::env; -use std::io::{Read, Write}; +use std::io::{Error, Read, Result, Write}; use std::net::{Ipv6Addr, Shutdown, TcpListener, TcpStream}; use std::time::Duration; extern crate getopts; +extern crate libc; use getopts::Options; +fn check_err(num: T) -> Result { + println!("check_err trying to convert {:?}", num); + if num < T::default() { + Err(Error::last_os_error()) + } else { + Ok(num) + } +} + +fn fork() -> Result { + check_err(unsafe { libc::fork() }).map(|pid| pid as u32) +} + +fn abandon_children() -> Result { + let res = check_err(unsafe { libc::signal(libc::SIGCHLD, libc::SIG_IGN) }); + println!("result from signal call with ({:?}, {:?}) is {:?} (FYI SIG_DFL={:?})", libc::SIGCHLD, libc::SIG_IGN, res, libc::SIG_DFL); + res +} + +fn exit() -> () { + unsafe { libc::exit(0) } +} + + fn handle_client(mut stream: TcpStream) { println!("Connection from {:?}", stream.peer_addr().unwrap()); - stream - .set_read_timeout(Some(Duration::from_secs(5))) - .expect("set_read_timeout failed"); - let mut buffer = [0; 128]; - match stream.read(&mut buffer) { - Ok(l) => { - let request = String::from_utf8_lossy(&buffer[..l]); - let name = request.trim_end(); - println!("Got {l:?} bytes request: \"{}\"", name); - stream - .write("Got this request\r\n".as_bytes()) - .expect("Write failed"); - stream.write(request.as_bytes()).expect("Write data failed"); - } - Err(e) => { - println!("Read error: {e:?}"); + let pid = fork().unwrap(); + if pid == 0 { + stream + .set_read_timeout(Some(Duration::from_secs(5))) + .expect("set_read_timeout failed"); + let mut buffer = [0; 128]; + match stream.read(&mut buffer) { + Ok(l) => { + let request = String::from_utf8_lossy(&buffer[..l]); + let name = request.trim_end(); + println!("Got {l:?} bytes request: \"{}\"", name); + stream + .write("Got this request\r\n".as_bytes()) + .expect("Write failed"); + stream.write(request.as_bytes()).expect("Write data failed"); + } + Err(e) => { + println!("Read error: {e:?}"); + } } + stream.shutdown(Shutdown::Both).expect("Shutdown failed"); + println!("Finished processing client"); + exit() + } else { + println!("parent returning, child pid was {:?}", pid); } - stream.shutdown(Shutdown::Both).expect("Shutdown failed"); - println!("Finished processing client"); } -fn main() -> std::io::Result<()> { +fn main() -> Result<()> { let args: Vec = env::args().collect(); let progname = args[0].clone(); let mut opts = Options::new(); @@ -52,9 +83,10 @@ fn main() -> std::io::Result<()> { panic!("Bad option for port {:?}", e) } }; + abandon_children().unwrap(); println!("Binding to port {:?}", p); - let listener = TcpListener::bind((Ipv6Addr::UNSPECIFIED, p)) - .expect("Could not bind to finger port"); + let listener = + TcpListener::bind((Ipv6Addr::UNSPECIFIED, p)).expect("Could not bind to finger port"); for stream in listener.incoming() { match stream { Ok(stream) => {