What is the correct way in Rust to create a timeout for a thread or a function?

前端 未结 2 669
抹茶落季
抹茶落季 2020-12-06 02:22

This is my code:

use std::net;
use std::thread;

fn scan_port(host: &str, port: u16) -> bool {
    let host = host.to_string();
    let port = port;
           


        
2条回答
  •  夕颜
    夕颜 (楼主)
    2020-12-06 02:29

    As @Shepmaster noted: it's a bad idea to terminate threads.

    What you can do instead is to give the thread a Sender through which it should notify you if it has successfully opened a connection (maybe even by sending you the handle). Then you can let your main thread sleep for the time you wish to wait. When your thread wakes up, it checks its corresponding Receiver for some sign of life from the thread. In case the thread did not answer, just release it into the wild by dropping the JoinHandle and the Receiver. It's not like it's consuming cpu-time (it's blocked), and it's not consuming too much memory. If it ever unblocks, it'll detect that the Sender is not connected and can shut down for good.

    Of course you should not have bazillions of these open threads, because they still use resources (memory and system thread handles), but on a normal system that's not too much of an issue.

    Example:

    use std::net;
    use std::thread;
    use std::sync::mpsc;
    
    fn scan_port(host: &str, port: u16) -> bool {
        let host = host.to_string();
        let port = port;
        let (sender, receiver) = mpsc::channel();
        let t = thread::spawn(move || {
            match sender.send(net::TcpStream::connect((host.as_str(), port))) {
                Ok(()) => {}, // everything good
                Err(_) => {}, // we have been released, don't panic
            }
        });
    
        thread::sleep(std::time::Duration::new(5, 0));
    
        match receiver.try_recv() {
            Ok(Ok(handle)) => true, // we have a connection
            Ok(Err(_)) => false, // connecting failed
            Err(mpsc::TryRecvError::Empty) => {
                drop(receiver);
                drop(t);
                // connecting took more than 5 seconds
                false
            },
            Err(mpsc::TryRecvError::Disconnected) => unreachable!(),
        }
    }
    

提交回复
热议问题