Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Channel moved in closure, that is later invoked by thread::spawn never receives the data even though the send succeeds #139019

Closed
nikola-jokic opened this issue Mar 27, 2025 · 2 comments
Labels
C-discussion Category: Discussion or questions that doesn't represent real issues.

Comments

@nikola-jokic
Copy link

I tried this code:

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

fn main() {
    let (tx, rx) = mpsc::sync_channel(2);
    let (done_tx, done_rx) = mpsc::sync_channel(2);
    panic_after(Duration::from_secs(5), move || {
        let mut count = 0;
        while let Ok(val) = rx.recv() {
            count += 1;
            if count == 2 {
                done_tx.send(()).expect("to succeed");
                break;
            }
        }
    });

    tx.send(1).unwrap();
    tx.send(2).unwrap();

    done_rx.recv().expect("to be done");
    println!("OK")
}

fn panic_after<T, F>(d: Duration, f: F) -> T
where
    T: Send + 'static,
    F: FnOnce() -> T,
    F: Send + 'static,
{
    let (done_tx, done_rx) = mpsc::channel();
    let handle = thread::spawn(move || {
        let val = f();
        done_tx.send(()).expect("Unable to send completion signal");
        val
    });

    match done_rx.recv_timeout(d) {
        Ok(_) => handle.join().expect("Thread panicked"),
        Err(_) => panic!("Thread took too long"),
    }
}

I expected to see this happen: To have OK printed. The recv blocks forever, and the send was never propagated. If I swap the panic_after to thread::spawn, it works. I'm not ruling out that I made some mistake, maybe, but I don't see how, since I pass the closure to both, and the panic_after invokes that closure.

Instead, this happened: panic occurs since the closure never receives the data

Meta

rustc --version --verbose:

rustc 1.85.0 (4d91de4e4 2025-02-17)
binary: rustc
commit-hash: 4d91de4e48198da2e33413efdcd9cd2cc0c46688
commit-date: 2025-02-17
host: x86_64-unknown-linux-gnu
release: 1.85.0
LLVM version: 19.1.7
Backtrace

thread 'main' panicked at src/main.rs:41:19:
Thread took too long
stack backtrace:
   0: rust_begin_unwind
             at /rustc/4d91de4e48198da2e33413efdcd9cd2cc0c46688/library/std/src/panicking.rs:692:5
   1: core::panicking::panic_fmt
             at /rustc/4d91de4e48198da2e33413efdcd9cd2cc0c46688/library/core/src/panicking.rs:75:14
   2: channel::panic_after
             at ./src/main.rs:41:19
   3: channel::main
             at ./src/main.rs:8:5
   4: core::ops::function::FnOnce::call_once
             at /home/nikola-jokic/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ops/function.rs:250:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.

@nikola-jokic nikola-jokic added the C-bug Category: This is a bug. label Mar 27, 2025
@rustbot rustbot added the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label Mar 27, 2025
@bjorn3
Copy link
Member

bjorn3 commented Mar 27, 2025

panic_after blocks until the spawned thread has finished. The spawned thread doesn't finish until it has received two items from the first channel. These items are not sent until after panic_after finishes however, so you get a deadlock.

@bjorn3 bjorn3 added C-discussion Category: Discussion or questions that doesn't represent real issues. and removed C-bug Category: This is a bug. labels Mar 27, 2025
@nikola-jokic
Copy link
Author

Oh my god, you are completely right! I'm being dumb 😞 ...
I was experimenting and completely forgot that panic_after doesn't spawn and continue...
Sorry I wasted your time!

@jieyouxu jieyouxu removed the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label Apr 2, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-discussion Category: Discussion or questions that doesn't represent real issues.
Projects
None yet
Development

No branches or pull requests

4 participants