When does a thread exit?

I'm using an spmc channel in my main thread which is feeding work to a thread pool of workers. As the docs say for the spmc crate, there is a RecvError which occurs when the main thread has finished sending work over to the worker threads and closes down the tx side of the channel. I do a match statement on the return of rx.recv(), if Ok(), I process the data provided in the channel, if Err(), I println!("A thread has exited.")

Strangely, although I only start 24 threads, the message "A thread has exited" appears like 500 times before the process finally exits, which leads me to believe that the threads are not necessarily exiting when that error occurs. However, when I searched online I did find a StackOverflow answer which stated that the way to make a thread terminate in Rust is to close the tx end of the channel. Is this correct? Does a RecvError mean the thread has terminated for sure?

Can you show your code? Are you sure your background threads are exiting the recv loop after seeing the error?

I think that's the problem - I was not aware that I needed to tell them to exit the loop when they receive the error - I thought the error automatically exited them... So having them exit the loop and move to the end of the thread closure code will make them exit by default?

I could try to write a MVCE if needed but heres the actual thread code:

 handles.push(thread::spawn(move || {
                let rx2 = ℞
                let ed = collect_args();
                //The following recv() will error out when the tx half of the channel has been taken down due to the main thread finishing
                    let pre_check_msg_status = rx2.recv(); // blocks current thread until msg avail
                    match pre_check_msg_status
                        Ok(val) =>
                            let is_it_valid = from_utf8(&val);
                            match is_it_valid
                                Ok(res) => 
                                    handle_item(res.to_string(), &ed, &reo);
                                Err(err) => continue
                        Err(e) => println!("Thread exit...\n")

You're essentially catching the error, and no, this will not implicitly exit the thread. From here, the control flow will just reach the end of the loop body and repeat. If you had unwrapped the Result instead to cause a panic on Err, then this would exit, but it's not recommended to use panics for normal control flow.

You could just break here, and then I would print your exit message outside the loop.

1 Like