multithreadingrusttcpshutdown

How to break from the blocking TcpListener::accept call?


I'm running the accept function of a TCP listener in a loop in a separate thread. I would like to shutdown this thread gracefully, but I can't see any kind of shutdown mechanism which I could use to break from accepting.

My current approach looks something like this:

use std::net::TcpListener;
use std::thread::spawn;

fn main() {
    let tcp_listener = TcpListener::bind((("0.0.0.0"), 0)).unwrap();
    let tcp_listener2 = tcp_listener.try_clone().unwrap();

    let t = spawn(move || {
        loop {
            match tcp_listener2.accept() {
                Ok(_) => { }
                Err(_) => { break; }
           }
        }
    });

    drop(tcp_listener);
    assert!(t.join().is_ok());
}

But that doesn't do the trick (probably because I drop only the cloned copy?). Any thought on how to properly shutdown such thread?

(for reference, I asked this question on rust user forum as well)


Solution

  • The question is a fundamental one, as in the end the accept() call translates down to a libc::accept() (see here and here).

    The solution would be to use nonblocking-io, look at mio for example.


    Edi: After some consideration I researched the possibility to interrupt the accept() using close(). It seems to be unreliable. But this turned up: Using shutdown(). TcpStream exposes this function, but it seems to be the only case. Might be a shortcoming of the API?