-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[Java] Observe error to avoid crash #22016
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,6 +4,7 @@ | |
| package com.microsoft.signalr; | ||
|
|
||
| import java.util.Map; | ||
| import java.util.concurrent.locks.ReentrantLock; | ||
|
|
||
| import org.slf4j.Logger; | ||
| import org.slf4j.LoggerFactory; | ||
|
|
@@ -26,6 +27,7 @@ class OkHttpWebSocketWrapper extends WebSocketWrapper { | |
| private WebSocketOnClosedCallback onClose; | ||
| private CompletableSubject startSubject = CompletableSubject.create(); | ||
| private CompletableSubject closeSubject = CompletableSubject.create(); | ||
| private final ReentrantLock closeLock = new ReentrantLock(); | ||
|
|
||
| private final Logger logger = LoggerFactory.getLogger(OkHttpWebSocketWrapper.class); | ||
|
|
||
|
|
@@ -87,14 +89,29 @@ public void onMessage(WebSocket webSocket, String message) { | |
| @Override | ||
| public void onClosing(WebSocket webSocket, int code, String reason) { | ||
| onClose.invoke(code, reason); | ||
| closeSubject.onComplete(); | ||
| try { | ||
| closeLock.lock(); | ||
| closeSubject.onComplete(); | ||
| } | ||
| finally { | ||
| closeLock.unlock(); | ||
| } | ||
| checkStartFailure(); | ||
| } | ||
|
|
||
| @Override | ||
| public void onFailure(WebSocket webSocket, Throwable t, Response response) { | ||
| logger.error("WebSocket closed from an error: {}.", t.getMessage()); | ||
| closeSubject.onError(new RuntimeException(t)); | ||
|
|
||
| try { | ||
| closeLock.lock(); | ||
| if (!closeSubject.hasComplete()) { | ||
| closeSubject.onError(new RuntimeException(t)); | ||
| } | ||
| } | ||
| finally { | ||
| closeLock.unlock(); | ||
| } | ||
| onClose.invoke(null, t.getMessage()); | ||
| checkStartFailure(); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there a chance that checkStartFailure() ever gets called before the Completable is returned from start() meaning we'd need to do the same ting for startSubject?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think that is technically possible, but very unlikely in practice. I'm not sure how the global error handler works in that case, because the startSubject will be observed by someone, they just haven't registered the handler by the time onError is called.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If it's possible, we should handle it.
We could test this by intentionally faulting the startSubject before returning. I expect it would also be crashing. How would the runtime even know the startSubject will be observed by someone in the future?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Read the docs for
This also implies that the "fix" in this PR might not be correct, and the error was happening through some other means. The docs also mention that if |
||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we check that the closeSubject hasn't already been completed with an error here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Calling onComplete should noop if the subject is already completed either with an error or without an error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@halter73 any other feedback?