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

This is my code:

use std::net; use std::thread; extern crate argparse; use argparse::{ArgumentParser, StoreTrue, Store}; fn scan_port(host: &str, port: u16) -> bool { let host = host.to_string(); let port = port; let t = thread::spawn(move || net::TcpStream::connect((host.as_str(), port)).is_ok()); t.join().unwrap() } 

How to create a situation when a thread is completed or killed if the connection did not end in N seconds?

The reason for all this is that Rust is not able to set the socket connection timeout, so I can not guarantee that the program will not get stuck.

+5
source share
2 answers

As @Shepmaster noted: this is a bad idea to stop streams.

Instead, you should give the Sender thread through which it should notify you if it successfully opened the connection (perhaps even sending you a hilt). Then you can leave your main sleep thread at the expected time. When your thread wakes up, it checks the appropriate Receiver for some signs of life from the thread. If the thread did not respond, just release it into the wild by discarding JoinHandle and Receiver . This is not like when it consumes CPU time (it is locked) and it does not consume too much memory. If it is ever unlocked, it will find that Sender not connected and can be disconnected forever.

Of course, you should not have bazillions of these open threads, because they still use resources (memory and system thread descriptors), but on a regular system, which is not a big problem.

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!(), } } 
+8
source

@Ker's answer will always wait 5 seconds, even if the connection ends faster. Here is a similar approach when the timeout and network request are executed on separate threads, and the first of them wins:

 let (sender, receiver) = mpsc::channel(); let tsender = sender.clone(); let t = thread::spawn(move || { match sender.send(Ok(net::TcpStream::connect((host.as_str(), port)))) { Ok(()) => {}, // everything good Err(_) => {}, // we have been released, don't panic } }); let timer = thread::spawn(move || { thread::sleep(Duration::from_millis(5000)); match tsender.send(Err(MyTimeoutError)) { Ok(()) => {}, // oops, we timed out Err(_) => {}, // great, the request finished already } }); return receiver.recv().unwrap(); 

But while you are doing this, you can simply use recv_timeout :

 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 } }); return receiver.recv_timeout(Duration::from_millis(5000)); 
0
source

Source: https://habr.com/ru/post/1245635/


All Articles