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

Fix memory leak in Downloads page #5949

Merged
merged 1 commit into from
Jan 19, 2021
Merged

Fix memory leak in Downloads page #5949

merged 1 commit into from
Jan 19, 2021

Conversation

ichorid
Copy link
Contributor

@ichorid ichorid commented Jan 19, 2021

Fixes #5934

The moral of the story: if you connect a QT signal to a QT object, don't expect it to be GCed in PyQT until you disconnect the signal manually (or better yet, just reuse the object).

@ichorid
Copy link
Contributor Author

ichorid commented Jan 19, 2021

retest this please

@sonarcloud
Copy link

sonarcloud bot commented Jan 19, 2021

Kudos, SonarCloud Quality Gate passed!

Bug A 0 Bugs
Vulnerability A 0 Vulnerabilities
Security Hotspot A 0 Security Hotspots
Code Smell A 0 Code Smells

No Coverage information No Coverage information
0.0% 0.0% Duplication

@drew2a
Copy link
Contributor

drew2a commented Jan 19, 2021

@ichorid congrats! 🎊

But I have a question. Are you sure about " don't expect it to be GCed in PyQT until you disconnect the signal manually"?

Because:

To connect slots to it, pass callbacks into connect. The connections are maintained through weakref, thus you don't need to search for them and disconnect whenever you're up to destroy some object.
https://pypi.org/project/qsignal/

BTW yes, we always should help GC: spesmilo/electrum#4905

@ichorid ichorid merged commit 62cf37e into Tribler:devel Jan 19, 2021
@ichorid
Copy link
Contributor Author

ichorid commented Jan 19, 2021

@ichorid congrats! confetti_ball

But I have a question. Are you sure about " don't expect it to be GCed in PyQT until you disconnect the signal manually"?

I learned the hard way never to trust PyQT promises... 😿

@drew2a
Copy link
Contributor

drew2a commented Jan 20, 2021

@ichorid @qstokkink what do you think, do we have to use something like:

class QAutoDisconnectableObject(QObject):
    def __init__(self):
        super().__init__()

        self.connected_signals = set()

        connect(self.destroyed, self.on_destroy)

    def connect(self, signal, callback):
        connect(signal, callback)
        self.connected_signals.add(signal)

    def on_destroy(self, *args):
        for signal in self.connected_signals:
            signal.disconnect()


class Table(QAutoDisconnectableObject):
    def __init__(self):
        super().__init__()
        self.connect(self.button.clicked, self.on_button_clicked)
        self.connect(self.button1.clicked, self.on_button1_clicked)

@qstokkink
Copy link
Contributor

@drew2a It seems useful to have a construction like that: I don't see any downsides to your suggestion.

@ichorid
Copy link
Contributor Author

ichorid commented Jan 20, 2021

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

ubuntu 18.04 LTS, ram filling up completely
3 participants