Open NobleMathews opened 2 days ago
send
method in SseEmitter
where lock acquisition order needs modification to prevent deadlocks. Reviewing this ensures consistent locking with StandardServletAsyncWebRequest
.Doesn't seem like we have fully grasped all the specifics of this ticket.
We have been tracking rather strange & random failures in our application: eventually, after many browser closed (and/or page refresh), our SSE event flux would not be sending anything anymore to new clients.
We identified that threads used for async tasks execution (AsyncSupportConfigurer) may deadlock due to a timing-dependant ABBA deadlock between SseEmitter sending and error handling on connection closed. If using the the default SimpleAsyncTaskExecutor which fires up a new Thread for each task, no user visible effect (except that some deadlocked unused threads are consumming resources on the server). But, if using a fixed number of threads (as we do in our application), the system may finally come to a halt (when all worker threads have been deadlocked).
What we think is going on (see example jstack trace captured):
Things are highly timing dependent, but we have been able to reproduce (with high probablity) our observed deadlocks: the idea is to emit big JSON objects (increasing the concurrency window) and normal objects concurrenty on the flux, while closing the browser
Reproduced with spring boot 3.3.2 (springframework 6.1.11) and also 3.3.3 (springframework 6.1.12)
Steps to reproduce:
See the minimalist example attached, with the following steps to reproduce:
Example of deadlock captured using jstack:
[demodeadlock.zip](