Closures causes self to never be dropped

⚓ Rust    📅 2025-12-06    👤 surdeus    👁️ 3      

surdeus

Hi, I'm having a problem with a function from Paho MQTT Rust library which is defined minimally as followed:

// Paho code
impl AsyncClient {
    pub fn set_connection_lost_callback(&self, cb: impl FnMut(&Self) + Send + 'static) {
        /* Stores the callback and when the client loses connection, it calls it. */
    }
}

I'm calling it in the constructor of my struct:

pub struct MyClient {
    client: paho::AsyncClient,
}

// Dummy impl
impl Drop for MyClient {
    fn drop(&mut self) {
        println!("Never prints");
    }
}

impl MyClient {
    pub fn new() -> Self {
        let client: paho::AsyncClient = ...;
        let (conn_lost_tx, conn_lost_rx) = async_channel::bounded(1);
        client.set_connection_lost_callback(move |_| {
            conn_lost_tx.send_blocking(());
        });
        glib::spawn_future_local(async move {
            loop {
                let Some(()) = conn_lost_rx.recv().await else {
                    return;
                };
                println!("Connection lost");
            }
        });
        Self {
            client
        }
    }
}

When client returned by new is dropped, it doesn't call dummy trait Drop. I tried closing the tx channel, passing weak channel to the callback, none of that works. It only works when the closure captures nothing:

client.set_connection_lost_callback(|_| {}); // Captures nothing

I'm not too much experienced in rust, but I think it has something to do with the closure being 'static and the capture itself capturing the stack memory from new function.

Thanks.

4 posts - 2 participants

Read full topic

🏷️ Rust_feed