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

[Test] Release unpooled buffer after usage to avoid leakage #862

Merged

Conversation

andsel
Copy link
Collaborator

@andsel andsel commented Oct 26, 2024

Release notes

[rn:skip]

What does this PR do?

Fix unpooled buffer leakage in tests.
Resolves leakage of Netty pooled buffers like in https://github.com/moquette-io/moquette/pull/872/checks#step:5:285

@andsel andsel added the bugfix label Oct 26, 2024
@andsel andsel self-assigned this Oct 26, 2024
@andsel andsel force-pushed the fix/test_realease_unpooled_buffer_created branch from 6ed1b1e to bc2c6e1 Compare November 16, 2024 18:33
@@ -559,6 +559,7 @@ public void close() {
// Update all not clean session with the proper expiry date
updateNotCleanSessionsWithProperExpire();
queueRepository.close();
pool.values().forEach(Session::cleanUp);
Copy link
Collaborator Author

@andsel andsel Nov 16, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When broker instance is shutdown, also all the reference counted objects kept live by inflight or qos2Receiving (phase 2 of QoS2) need to be un-referenced, so that others Netty libraries doesn't expose buffer leakage when just the broker part is stopped.

@andsel andsel force-pushed the fix/test_realease_unpooled_buffer_created branch 11 times, most recently from fda7eaf to 65d6154 Compare November 23, 2024 18:18
@andsel andsel marked this pull request as ready for review November 23, 2024 18:20
@andsel andsel requested a review from hylkevds November 23, 2024 18:21
@andsel
Copy link
Collaborator Author

andsel commented Nov 23, 2024

Hi @hylkevds I ask if you could review this PR, you have previous experience with buffer leakage :-)

@hylkevds
Copy link
Collaborator

Hi @hylkevds I ask if you could review this PR, you have previous experience with buffer leakage :-)

Sure, I'll go over it.

@hylkevds
Copy link
Collaborator

hylkevds commented Nov 24, 2024

Man, finding buffer leaks in tests is annoying! At the time the leak warning pops up, there is no relation to the test that actually caused the leak!

So I made a modified netty ResourceLeakDetector.java

Then a search/replace on all tests. Multi-line regex Search (including final line ending):

    @Test
    public void ([a-zA-Z0-9_-]+)\(\)([^\n]+)

replace:

    @Test
    public void $1()$2
        System.out.println("$1");
        io.netty.util.ResourceLeakDetector.statusHint = "$1";

And netty will tell the test that caused the resource leak:

Created at: receiveInflightPublishesAfterAReconnect

Now to find the actual cause :)

@andsel
Copy link
Collaborator Author

andsel commented Nov 25, 2024

I've done manually 😄 by dissection, finding the minimal 2 or 3 tests that made the problem to trigger.
Your suggestion is really nice! We can add that in a follow up PR. Just one question, how do you replace the default Netty's ResourceLeakDetector ? Do you create a customized Netty jar?

@hylkevds
Copy link
Collaborator

hylkevds commented Nov 25, 2024

Yep, I patched Netty and re-build the netty-common jar.

git clone [email protected]:netty/netty.git#
cd netty/common
git checkout netty-4.1.100.Final
curl https://gist.githubusercontent.com/hylkevds/44b238676ee727d20ed451b208c7ff2a/raw/c40464507f6e42bc02fd3ea12b129b93f9273dae/ResourceLeakDetector.java > src/main/java/io/netty/util/ResourceLeakDetector.java 
mvn install -DskipTests=true

Maven then automatically picks up the patched version.

The problem I had with running individual tests is that the garbage collection was never triggered, so the leak-detection also never triggered...

@andsel
Copy link
Collaborator Author

andsel commented Nov 25, 2024

Maybe it worthwhile to propose on the upstream Netty project, that hint would help also others, I think.

@hylkevds
Copy link
Collaborator

I could not imagine Netty didn't already have something similar. The ResourceLeakDetector has something called initialHint that seemed to do something similar... It was just some digging to find out how to set that!

Add this to Utils:

    private static boolean resourceLeakDetectorFactoryOverridden = false;

    public static void setResourceLeakHint(String hint) {
        if (!resourceLeakDetectorFactoryOverridden) {
            ResourceLeakDetectorFactory.setResourceLeakDetectorFactory(new HintingResourceLeakDetectorFactory());
            resourceLeakDetectorFactoryOverridden = true;
        }
        HintingResourceLeakDetector.initialHint = hint;
    }

    public static class HintingResourceLeakDetector<T> extends ResourceLeakDetector<T> {

        public static String initialHint = "";

        public HintingResourceLeakDetector(Class<T> resource, int samplingInterval, long maxActive) {
            super(resource, samplingInterval, maxActive);
        }

        @Override
        protected Object getInitialHint(String resourceType) {
            return initialHint;
        }
    }

    public static class HintingResourceLeakDetectorFactory extends ResourceLeakDetectorFactory {

        @Override
        public <T> ResourceLeakDetector<T> newResourceLeakDetector(Class<T> resource, int samplingInterval, long maxActive) {
            return new HintingResourceLeakDetector(resource, samplingInterval, maxActive);
        }
    }

And then in each @test (using the search & replace):

io.moquette.Utils.setResourceLeakHint("sendConnectOnDisconnectedConnection");

And no need to patch Netty anymore!

@andsel
Copy link
Collaborator Author

andsel commented Nov 26, 2024

@hylkevds this is a good hint, it will deserve a follow up PR, if you want to contribute I'll be happy t review. Just a note, instead of using System.out.println maybe worthwhile to use a global test logger, so that we can switch on and off from log4j.properties under test folder.

Copy link
Collaborator

@hylkevds hylkevds left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes look good. There seems to be just one leak left to find.

@andsel andsel force-pushed the fix/test_realease_unpooled_buffer_created branch from 65d6154 to facc759 Compare November 27, 2024 09:25
@andsel andsel merged commit a91fac5 into moquette-io:main Nov 27, 2024
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants