antoyo / relm

Idiomatic, GTK+-based, GUI library, inspired by Elm, written in Rust
MIT License
2.43k stars 78 forks source link

Who manages the lifetime of components? #127

Closed boblehest closed 3 years ago

boblehest commented 6 years ago

Reading the http example, I was curious about who manages the lifetime of the http component (created here), and it seems that the component itself is moved into the stream's callback, and kept there.

Who's supposed to drop the component when it's outlived its purpose? Even closing the returned stream does not cause the component to get dropped. I managed to drop it by replacing the stream's callback (http.set_callback(|_| ());). This seems very unergonomic. Am I doing it wrong? Any input is appreciated.

antoyo commented 6 years ago

Do you save the result of execute somewhere (perhaps by moving it into a callback)? The callback should be dropped by itself when the EventStream returned by execute is dropped. If you save it in your model, you could save it as an Option so that you can take() it to destroy the component.

Edit: Wait, I think there's something wrong in the example. Since the http stream is dropped, the callback should never be called. I'll have to check in more detail.

boblehest commented 6 years ago

Just so we're on the same page; I'm only talking about what I'm seeing in the example — not about any code I've written myself. And when I say that the component is moved into the stream's callback, I'm referring to what happens here (in init_component, which is called by execute).

The callback should be dropped by itself when the EventStream returned by execute is dropped.

Yeah, that's what I was expecting, but I noticed that it's not what's happening. :/

antoyo commented 6 years ago

It seems there's a reference cycle. I'll check that.

kevinpoitra commented 5 years ago

It seems like I'm running into the same bug. In an application I'm writing, I facilitate HTTP requests exactly as the http example does. What I'm noticing is that if I wrap the code that creates the http EventStream and the execute function itself in a for loop (to help exacerbate the issue) and run that for loop every few seconds is that:

silwol commented 5 years ago

After stumbling over the problem of resources being kept alive after removing widgets, I created a small test program that logs the dropping of an item which is placed inside a widget struct. It clearly demonstrates that the resources are not freed by doing the following:

Maybe I'm doing something wrong here, or I don't understand how this should work, but in my opinion, the widget struct should be dropped including it's enclosed fields.

I tested with relm 0.17.0 as well as the feature/remove-gsource branch rebased against current master. They show the same behavior.

main.rs.txt

antoyo commented 4 years ago

@silwol: I started a new branch that should fix this issue. It's not ready yet (many errors to fix), but it should fix this issue. Could you please try it?

silwol commented 4 years ago

@antoyo Thanks for the notification. I just tried my example from the comment above, and now the items seem to get drop at the expected moments, :+1: from me.