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

Memory leak in SinkOneMulticast #3001

Closed
anuchandy opened this issue Apr 7, 2022 · 2 comments
Closed

Memory leak in SinkOneMulticast #3001

anuchandy opened this issue Apr 7, 2022 · 2 comments
Labels
type/bug A general bug
Milestone

Comments

@anuchandy
Copy link

It looks like SinkOneMulticast keeps track of subscribers even after the disposition of corresponding subscriptions.

Here is the repro:

// Create a SinkOne
Sinks.One<Boolean> signalSink = Sinks.one();

// First set of 3 subscriptions (A1, A2, A3)
//
Disposable disposableA1 = signalSink.asMono()
    .doOnSuccess(b -> {
        System.out.println("doOnSuccessA1");
    })
    .doFinally(signalType -> {
        System.out.println("doFinallyA1:" + signalType);
    })
    .subscribe();

Disposable disposableA2 = signalSink.asMono()
    .doOnSuccess(b -> {
        System.out.println("doOnSuccessA2");
    })
    .doFinally(signalType -> {
        System.out.println("doFinallyA2:" + signalType);
    })
    .subscribe();

Disposable disposableA3 = signalSink.asMono()
    .doOnSuccess(b -> {
        System.out.println("doOnSuccessA3");
    })
    .doFinally(signalType -> {
        System.out.println("doFinallyA3:" + signalType);
    })
    .subscribe();

// Composite Disposable for first set (A1, A2, A3)
Disposable.Composite disposablesA = Disposables.composite();
disposablesA.add(disposableA1);
disposablesA.add(disposableA2);
disposablesA.add(disposableA3);

// Second set of 3 subscriptions (B1, B2, B3)
//
Disposable disposableB1 = signalSink.asMono()
    .doOnSuccess(b -> {
        System.out.println("doOnSuccessB1");
    })
    .doFinally(signalType -> {
        System.out.println("doFinallyB1:" + signalType);
    })
    .subscribe();

Disposable disposableB2 = signalSink.asMono()
    .doOnSuccess(b -> {
        System.out.println("doOnSuccessB2");
    })
    .doFinally(signalType -> {
        System.out.println("doFinallyB2:" + signalType);
    })
    .subscribe();

Disposable disposableB3 = signalSink.asMono()
    .doOnSuccess(b -> {
        System.out.println("doOnSuccessB3");
    })
    .doFinally(signalType -> {
        System.out.println("doFinallyB3:" + signalType);
    })
    .subscribe();


// Composite Disposable for second set  (B1, B2, B3)
Disposable.Composite disposablesB = Disposables.composite();
disposablesB.add(disposableB1);
disposablesB.add(disposableB2);
disposablesB.add(disposableB3);

As expected SinkOneMulticast tracks 6 subscribers (3 from the first and 3 from the second set)

SinkOneMulticastAB

Now dispose of the first set (A1, A2, A3)

// Dispose only the first set
disposablesA.dispose();

doFinally is invoked for the first set as expected

doFinallyA1:cancel
doFinallyA2:cancel
doFinallyA3:cancel

but SinkOneMulticast won't release those 3 subscribers but continues to hold reference to those

SinkOneMulticastB

SinkOneMulticast keeps holding those references until the sink emits

signalSink.tryEmitValue(true);

SinkOneMulticastCleared

The above behavior of SinkOneMulticast holding references to disposed subscribers blocks its GC collection. This leads to memory leaks in the applications.

The application might have different components listening (subscribed) to the SinkOne. Some of the components may not be interested in the signal at a later point and dispose the subscriptions (for example, in the component close() method). When huge number of such components are created and closed, those subscribers in SinkOne leads to memory leak.

@reactorbot reactorbot added the ❓need-triage This issue needs triage, hasn't been looked at by a team member yet label Apr 7, 2022
@simonbasle simonbasle added type/bug A general bug and removed ❓need-triage This issue needs triage, hasn't been looked at by a team member yet labels Apr 7, 2022
@simonbasle simonbasle added this to the 3.4.17 milestone Apr 7, 2022
@simonbasle
Copy link
Contributor

good catch, thanks for reporting @anuchandy ! one liner fix upcoming 😄

@JonathanGiles
Copy link

Thanks @simonbasle!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type/bug A general bug
Projects
None yet
Development

No branches or pull requests

4 participants