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

Who manages the lifetime of components? #127

Closed
Tracked in #102
boblehest opened this issue Jul 20, 2018 · 7 comments
Closed
Tracked in #102

Who manages the lifetime of components? #127

boblehest opened this issue Jul 20, 2018 · 7 comments
Milestone

Comments

@boblehest
Copy link

@boblehest boblehest commented Jul 20, 2018

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
Copy link
Owner

@antoyo antoyo commented Jul 20, 2018

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
Copy link
Author

@boblehest boblehest commented Jul 21, 2018

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
Copy link
Owner

@antoyo antoyo commented Jul 21, 2018

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

@kevinpoitra
Copy link

@kevinpoitra kevinpoitra commented Jan 24, 2019

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:

  • The memory usage of the program will rise from a starting point of ~14MB to ~400MB, increasing steadily with each iteration of the loop. It'll seemingly stop being able to issue new HTTP requests at random points every time I restart the application - sometimes at 70MB, sometimes at 400MB, and anything in between.
  • After a while, the program will slow down to a crawl.
  • Eventually, (I assume) the program will consume all available handles. This not only causes the program to be unable to issue any further HTTP requests, but it also locks up the entire computer - Firefox, for example, won't load any pages or even show any connection errors, it'll just show a white screen and do nothing, and similar issues can be found with any application that connects to the internet. As soon as I close the application, Firefox and everything else starts working again.

@antoyo antoyo mentioned this issue May 14, 2019
@silwol
Copy link

@silwol silwol commented Aug 15, 2019

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:

  • For control purposes: Explicitly creating the widget struct (in this case label::W) inside a scope. When the scope is left, the drop message of the enclosed item is printed.
  • Creating a Component<label::W> through create_component() inside a scope. When the scope is left, I would expect the drop message of the enclosed item to be printed, but that doesn't happen.
  • Show a window to which a single label::W widget can be added and removed by clicking a button. Here again, I would expect the drop message of the enclosed item to be printed whenever the remove button gets clicked, but again that doesn't happen.

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
Copy link
Owner

@antoyo antoyo commented May 3, 2020

@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
Copy link

@silwol silwol commented May 3, 2020

@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, 👍 from me.

@antoyo antoyo added this to the 1.0 milestone Nov 28, 2020
@antoyo antoyo mentioned this issue Nov 28, 2020
39 tasks
@antoyo antoyo mentioned this issue Nov 29, 2020
@antoyo antoyo closed this in #245 Nov 30, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

4 participants