Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does my program that spawns threads that iterate over MPSC channels never exit? [duplicate]

Tags:

rust

I made the following program:

use std::process;
use std::sync::mpsc;
use std::thread;
use std::time::Duration;

fn main() {
    let (tx, rx) = mpsc::channel();
    let t1 = thread::spawn(move || {
        for i in 0..10 {
            if i != 9 {
                let msg = i32::from(i);
                tx.send(msg).unwrap();
            } else {
                println!("Greetings from process {} of 10!", i);
                for received in rx.iter().take(10) {
                    println!("Greetings from process {} of 10!", received);
                    thread::sleep(Duration::from_secs(1));
                }
                process::exit(1);
            }
        }
    });
    t1.join().unwrap();
}

The program never ends; it executes all the code but it never finalizes. Can someone give me some help?

like image 787
Felipe Queiroz Barreto Avatar asked Nov 16 '25 10:11

Felipe Queiroz Barreto


1 Answers

The issue is that iter() on a Receiver is a blocking call. So since the Sender didn't "hang up" yet, then it will remain blocked, as you only ever send 9 messages. If you attempt to take() 9 or less (i.e. at most what is sent), then the for loop will end as expected.

Alternatively, you can either (1) use try_iter(), which will stop the iteration when there are no more pending values, or (2) you'd need to "hang up" the Sender prior to entering the for loop, which you can do by calling drop(tx).

} else {
    drop(tx);
//  ^^^^^^^^
    println!("Greetings from process {} of 10!", i);
    for received in rx.iter().take(10) {
        println!("Greetings from process {} of 10!", received);
        thread::sleep(Duration::from_secs(1));
    }
    process::exit(1);
}

or

} else {
    println!("Greetings from process {} of 10!", i);
    for received in rx.try_iter().take(10) {
//                     ^^^^^^^^
        println!("Greetings from process {} of 10!", received);
        thread::sleep(Duration::from_secs(1));
    }
    process::exit(1);
}

This is of course, ignoring the fact that what you're trying to do, is somewhat confusing, as in why a thread is sending/receiving to itself. However, this will solve the "does not exit" issue.

like image 53
vallentin Avatar answered Nov 19 '25 09:11

vallentin