You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
[fix] Fix memory leak caused by incorrect close and destruction (#54)
Fixes#55
### Motivation
1. When a producer or consumer is closed, the reference is still stored
in `ClientImpl`. If a client kept creating producers or consumers,
the memory usage would not reduce.
2. When the `HandlerBase::connection_` field is modified, the
`removeProducer` or `removeConsumer` method is not called. Then these
producers and consumers will be cached in the connection until the
connection is closed.
3. The `PartitionedProducerImpl` and `MultiTopicsConsumerImpl` have
cyclic references, when a `Producer` or `Consumer` instance goes out
of the scope, the destructors are not called. When I used GDB to
debug them, I found the reference counts were both greater than 1.
### Modifications
Let's use "handlers" to represent "producers and consumers".
1. In `ClientImpl`, use `SynchronizedHashMap` to store references of
handlers, as well as the `cleanupXXX` methods to remove a handler.
2. Add `HandlerBase::beforeConnectionChange` method, which is called
before `connection_` is modified. Disallow the access to
`connection_` from derived classes.
3. Avoid `shared_from_this()` being passed into callbacks in ASIO
executors for `PartitionedProducerImpl` and
`MultiTopicsConsumerImpl`.
This PR also unifies the `shutdown` implementations for handlers and
call `shutdown` in the destructors.
1. Cancel the timers
2. Unregister itself from `ClientImpl` and `ClientConnection`
3. Set the create future with `ResultAlreadyClosed`
4. Set the state to `Closed`
It's called when:
- the destructor is called
- `closeAsync` is completed
- `unsubscribeAsync` is completed with ResultOk
### Verifications
`ShutdownTest` is added to verify the following cases:
- a single topic
- a partitioned topic (multiple topics)
- a partitioned topic with regex subscription
`testClose` verifies `shutdown` when `closeAsync` and `unsubscribeAsync`
are called. `testDestructor` verifies `shutdown` when handlers go out of
the scope and the destructors are called.
0 commit comments