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

WebSocketService leaks subscriptions and requests after disconnect #2121

Closed
Shohou opened this issue Dec 2, 2024 · 0 comments · Fixed by #2129
Closed

WebSocketService leaks subscriptions and requests after disconnect #2121

Shohou opened this issue Dec 2, 2024 · 0 comments · Fixed by #2129
Labels
bug A bug in behaviour or functionality

Comments

@Shohou
Copy link
Contributor

Shohou commented Dec 2, 2024

Subscription leak

WebSocketService has a field subscriptionForId which is map with subscription objects. The only way for subscription to be removed from this map is through dispose call. If websocket gets disconnected onWebSocketClose method is called and all subscriptions are notified through onError method, but they are not removed from map. When subsriptions receives onError call it cannot call dispose anymore as it is already in cancelled status and object in subscriptionForId field stays there forever. Now if I call WebSocketService.connect to reconnect websocket and do another subscription and repeat disconnect-reconnect-subscribe multiple times, each cycle create another object in subscriptionForId map and during disconnect all of them are notified in closeOutstandingSubscriptions() and as that BehaviorSubject is already cancelled it spams errors in console:

io.reactivex.exceptions.UndeliverableException: The exception could not be delivered to the consumer because it has already canceled/disposed the flow or the exception has nowhere to go to begin with. Further reading: https://github.com/ReactiveX/RxJava/wiki/What's-different-in-2.0#error-handling | java.io.IOException: Connection was closed
        at io.reactivex.plugins.RxJavaPlugins.onError(RxJavaPlugins.java:367)
        at io.reactivex.subjects.BehaviorSubject.onError(BehaviorSubject.java:276)
        at org.web3j.protocol.websocket.WebSocketService.lambda$closeOutstandingSubscriptions$9(WebSocketService.java:569)
        at java.base/java.util.concurrent.ConcurrentHashMap$ValuesView.forEach(ConcurrentHashMap.java:4783)
        at org.web3j.protocol.websocket.WebSocketService.closeOutstandingSubscriptions(WebSocketService.java:565)
        at org.web3j.protocol.websocket.WebSocketService.onWebSocketClose(WebSocketService.java:549)
        at org.web3j.protocol.websocket.WebSocketService$1.onClose(WebSocketService.java:167)
        at java.base/java.util.Optional.ifPresent(Optional.java:178)
        at org.web3j.protocol.websocket.WebSocketClient.onClose(WebSocketClient.java:67)
        at org.java_websocket.client.WebSocketClient.onWebsocketClose(WebSocketClient.java:671)
        at org.java_websocket.WebSocketImpl.closeConnection(WebSocketImpl.java:562)
        at org.java_websocket.WebSocketImpl.closeConnection(WebSocketImpl.java:586)
        at org.java_websocket.client.WebSocketClient.run(WebSocketClient.java:496)
        at java.base/java.lang.Thread.run(Thread.java:1583)
Caused by: java.io.IOException: Connection was closed
        at org.web3j.protocol.websocket.WebSocketService.lambda$closeOutstandingSubscriptions$9(WebSocketService.java:568)
        ... 11 more
Exception in thread "WebSocketConnectReadThread-386" io.reactivex.exceptions.UndeliverableException: The exception could not be delivered to the consumer because it has already canceled/disposed the flow or the exception has nowhere to go to begin with. Further reading: https://github.com/ReactiveX/RxJava/wiki/What's-different-in-2.0#error-handling | java.io.IOException: Connection was closed
        at io.reactivex.plugins.RxJavaPlugins.onError(RxJavaPlugins.java:367)
        at io.reactivex.subjects.BehaviorSubject.onError(BehaviorSubject.java:276)
        at org.web3j.protocol.websocket.WebSocketService.lambda$closeOutstandingSubscriptions$9(WebSocketService.java:569)
        at java.base/java.util.concurrent.ConcurrentHashMap$ValuesView.forEach(ConcurrentHashMap.java:4783)
        at org.web3j.protocol.websocket.WebSocketService.closeOutstandingSubscriptions(WebSocketService.java:565)
        at org.web3j.protocol.websocket.WebSocketService.onWebSocketClose(WebSocketService.java:549)
        at org.web3j.protocol.websocket.WebSocketService$1.onClose(WebSocketService.java:167)
        at java.base/java.util.Optional.ifPresent(Optional.java:178)
        at org.web3j.protocol.websocket.WebSocketClient.onClose(WebSocketClient.java:67)
        at org.java_websocket.client.WebSocketClient.onWebsocketClose(WebSocketClient.java:671)
        at org.java_websocket.WebSocketImpl.closeConnection(WebSocketImpl.java:562)
        at org.java_websocket.WebSocketImpl.closeConnection(WebSocketImpl.java:586)
        at org.java_websocket.client.WebSocketClient.run(WebSocketClient.java:496)
        at java.base/java.lang.Thread.run(Thread.java:1583)
Caused by: java.io.IOException: Connection was closed
        at org.web3j.protocol.websocket.WebSocketService.lambda$closeOutstandingSubscriptions$9(WebSocketService.java:568)
        ... 11 more

There is also requestForId map which I think behaves in a similar way, but as requests are not long living objects it's harder to reproduce and so I didn't check.

Steps To Reproduce

subscribe with WebSocketService by calling eth_subscribe for newHeads
disable your internet connection
reconnect
resubsribe
check exceptions and see how there is more and more exception spam after each disconnect-connect-subsribe

Expected behavior

I expect subscription objects to be cleared after websocket disconnects

Actual behavior

spam in console during disconnects, some lost memory I guess

Environment

  • Web3j version - 4.12.2

Additional context

Ask me if more information is needed

@Shohou Shohou added the bug A bug in behaviour or functionality label Dec 2, 2024
Shohou pushed a commit to Shohou/web3j that referenced this issue Dec 16, 2024
Shohou pushed a commit to Shohou/web3j that referenced this issue Dec 16, 2024
Shohou pushed a commit to Shohou/web3j that referenced this issue Dec 17, 2024
Shohou added a commit to Shohou/web3j that referenced this issue Dec 17, 2024
gtebrean added a commit that referenced this issue Dec 17, 2024
#2121 - clear subscriptionForId map after websocket disconnects
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug A bug in behaviour or functionality
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant