Channel closed before being dropped?

I have a TCP server that handles file uploads which is responsible for writing the files to the disk and update a metadata file.

For this task I created a thread as soon as the server starts to listening in order to write to the metadata file and for each new incoming request new thread is spawned and sends the file metadata to the other thread.

But the problem here is after first message sent using the tx_pipe the channel is closed. But how the channel is being dropped if the origin Sender, tx, didn't went out of scope and tx_pipe is a clone of tx?

pub fn listen(&mut self) -> Result<(), std::io::Error>
    let listener = TcpListener::bind("0.0.0.0:7878").unwrap();
    let (tx, rx) = channel();

    let meta_writer = thread::spawn(move || {
        let received: Box<Metadata> = rx.recv().unwrap();
        println!("Meta:  {:#?}", received);
    });

    
    for stream in listener.incoming() {
        let tx_pipe = tx.clone();

        let mut stream = stream.unwrap();

         let t = thread::spawn(move ||
             let meta  = TcpServer::handle_file(stream);
             let packet= Box::new(meta);
               
             match tx_pipe.send(packet) {
                Ok(x) => println!("All good"),
                Err(err) => println!("Erro: {}", err),
             }
         });
    }

Disclaimer, I don't know much about this kind of problem :sweat_smile:

But it seems to me that your program can indeed receive only 1 message, and that occurs in meta_writer.
The behavior of meta_writer, from what I can see, is to:

  1. Block until it receives a message
  2. Print the message
  3. Die

So once it received the first message, it dies, drops rx, and the channel is closed.

1 Like

Hmm interesting, did not thought about this possibility.
I assumed that as long as the senders kept alive the receiver wouldn't be dropped

As long as the senders are kept alive, the recv() method wont return None, but if you let the receiver go out of scope it is dropped, just like any other variable would be.

Dropping is not a dynamic property of a value. The time/place when/where a value is dropped is for the most part determined at compile-time (except if you have shared ownership, e.g. Rc, but here you don't). As soon as your move closure returns, rx does go out of scope and is therefore dropped.

1 Like

I found a solution for the problem, that idk if its the best one but it works

instead of

let meta_writer = thread::spawn(move || {
        let received: Box<Metadata> = rx.recv().unwrap();
        println!("Meta:  {:#?}", received);
    });

which will drop de receiver after id finishes the job, I'm using

let meta_writer = thread::spawn(move || {
    for received in rx {
        println!("{:?}", rx);
    }
});

Which will keep waiting for messages to arrive in the channel

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.