Closed waitshang closed 3 years ago
Thanks for the report and the sample. Please note that Spring Boot 2.3.x has reached the end of its open-source support period. I updated the sample to 2.4.9 and the problem still occurs. The analysis that follows was performed on Spring Boot 2.4.9 (Undertow 2.2.9 and Tomcat 9.0.50).
When emitter.send(i)
is called after the client has disconnected, it fails with an IOException
due to a broken pipe. This causes SseEmitter
to set its sendFailed
flag to true
. The purpose of this flag is described by its javadoc:
After an I/O error, we don't call
completeWithError
directly but wait for the Servlet container to call us viaAsyncListener#onError
on a container thread at which point we callcompleteWithError
. This flag is used to ignore further calls tocomplete
orcompleteWithError
that may come for example from an application try-catch block on the thread of the I/O error.
When you're using Undertow, the expected call to AsyncListener#onError
never comes and, instead, the async request eventually times out. If you use Tomcat, the onError
call does occur and your onError
handler is called as expected.
This looks like an Undertow bug to me but we'll transfer the issue to the Framework team just in case there's anything that they can do.
Thanks for the report and the sample. Please note that Spring Boot 2.3.x has reached the end of its open-source support period. I updated the sample to 2.4.9 and the problem still occurs. The analysis that follows was performed on Spring Boot 2.4.9 (Undertow 2.2.9 and Tomcat 9.0.50).
When
emitter.send(i)
is called after the client has disconnected, it fails with anIOException
due to a broken pipe. This causesSseEmitter
to set itssendFailed
flag totrue
. The purpose of this flag is described by its javadoc:After an I/O error, we don't call
completeWithError
directly but wait for the Servlet container to call us viaAsyncListener#onError
on a container thread at which point we callcompleteWithError
. This flag is used to ignore further calls tocomplete
orcompleteWithError
that may come for example from an application try-catch block on the thread of the I/O error.When you're using Undertow, the expected call to
AsyncListener#onError
never comes and, instead, the async request eventually times out. If you use Tomcat, theonError
call does occur and youronError
handler is called as expected.This looks like an Undertow bug to me but we'll transfer the issue to the Framework team just in case there's anything that they can do.
Thanks a lot. I will pay attention to this problem continually.
Sever-Sent Events (SseEmitter) works unexpectedly on Undertow server (spring-boot-starter-undertow). The method
SseEmitter.onError()
cann't call back when client disconnected from server. This phenomenon does not happen when using Tomcat server.Code
Result
When disconnected from client, the
onError
andonCompletion
message both not printed immediately.After a while, only the
onCompletion
message printed.Attachments
undertow-sse-demo.zip