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<T: std::fmt::Debug + Ord + Default>(num: T) -> Result<T> {
+    println!("check_err trying to convert {:?}", num);
+    if num < T::default() {
+        Err(Error::last_os_error())
+    } else {
+        Ok(num)
+    }
+}
+
+fn fork() -> Result<u32> {
+    check_err(unsafe { libc::fork() }).map(|pid| pid as u32)
+}
+
+fn abandon_children() -> Result<usize> {
+    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<String> = env::args().collect();
     let progname = args[0].clone();
     let mut opts = Options::new();
             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) => {