rpc: implement Drop for KaspaRpcClient to prevent resource leaks#863
rpc: implement Drop for KaspaRpcClient to prevent resource leaks#863atharaldsen wants to merge 4 commits intokaspanet:masterfrom
Conversation
|
I believe it requires writing a test that demonstrates initial problem and fix. Creation of daemon. You need to add wrpc client. Other references of how to test anything. |
|
There are client examples in https://github.com/kaspanet/rusty-kaspa/tree/master/rpc/wrpc/examples They should probably be moved into integration tests. (albeit integration tests don't do wasm coverage) |
|
thanks @biryukovmaxim and @aspect :-) Added. |
|
https://github.com/biryukovmaxim/rusty-kaspa/tree/fix-rpc-client-drop-enhance-testing @aspect could you please give more detailed instructions, where to start such investigation and what may still hold references? if you have some |
|
Thanks for digging into this @biryukovmaxim - you're right. I traced the circular reference with Claude and found:
Plus the spawned tasks in So even when the user drops What would be the preferred fix here?
Happy to implement whichever approach you think fits the architecture best. |
1 and 2 are both acceptable to me. I would prefer 2. My intuition tells it will be simpler and will have less changes |
Implement RAII pattern for KaspaRpcClient by adding Drop trait to the Inner struct. When the client is dropped while still connected: - Logs a warning advising users to call disconnect() explicitly - Closes notification channels synchronously - Spawns a fire-and-forget task for async cleanup (rpc_client.shutdown) This prevents resource leaks when users forget to call disconnect(), while still recommending explicit cleanup for guaranteed shutdown. The Drop is implemented on Inner (not KaspaRpcClient) because KaspaRpcClient is Clone via Arc<Inner>, so Drop should only fire when the last reference is dropped. Fixes kaspanet#683
) Add test that validates the Drop implementation cleans up resources when client is dropped without explicit disconnect() call. - Add kaspa-wrpc-client dependency to integration tests - Add new_wrpc_client() method to test infrastructure - Add daemon_wrpc_client_drop_test integration test Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Based on biryukovmaxim's suggestion (option 2) and Anton's feedback: - Clear notifier in stop_notifier() to break reference cycle (Inner → Notifier → Subscriber → Arc<Inner>) - Add auto_cleanup_on_drop flag to gate Drop cleanup behavior - Default to auto-cleanup enabled for safety This allows Inner::drop() to properly fire after disconnect() is called, while still providing flexibility for explicit lifecycle management.
686b2db to
2b24787
Compare
|
Addressed the feedback from @biryukovmaxim and @aspect: Changes:
The cycle-breaking is the key fix — without it, Ready for re-review. |
|
@atharaldsen I pushed test that shows that inner is still not freed. I believe currently this branch should focus on making the test pass. another thing is that Inner accepts bool flag, however it's part of private API. maybe I missed that but I believe it should client should have constructor-methor or builder/params to disable it. otherwise its pointless since no one can disable cleaning - meaning it always work with true flag |
Summary
Implement RAII pattern for
KaspaRpcClientby addingDroptrait to prevent resource leaks.Changes
initiate_cleanup()method toInnerstructDrop for Innerthat calls cleanup when last reference is droppedKaspaRpcClientBehavior
When client is dropped while still connected:
Why Drop on Inner?
KaspaRpcClientisCloneviaArc<Inner>, so Drop fires only when the last reference is dropped.Fixes #683