Skip to content

Rest Endpoints getting timed out (possible dead lock in WebSocketUpgradeFilter) after upgrade to spring boot 4.0.0 #14206

@saikatkar

Description

@saikatkar

Jetty version(s)
12.1.4

Jetty Environment
ee11

HTTP version
1.1

Java version/vendor (use: java -version)
Openjdk 17
OS type/version
MacOs 15.6.1

Description
We were using spring boot 3.5.8. After upgrading to 4.0.0 we are facing this problem where all of our rest apis are getting timed out as the request is stuck after its reaching the server.
On taking the thread dump this is what we found

   2025-12-17 16:47:02
Full thread dump Java HotSpot(TM) 64-Bit Server VM (17.0.8+9-LTS-211 mixed mode, emulated-client, sharing):

Threads class SMR info:
_java_thread_list=0x0000600000c18440, length=43, elements={
0x000000012d029600, 0x000000012d02be00, 0x000000012b052c00, 0x000000012d80c200,
0x000000012d029c00, 0x0000000118808200, 0x000000012d80c800, 0x000000012a010400,
0x000000012c808200, 0x000000012c897000, 0x000000012b04fe00, 0x000000012a011a00,
0x000000012a190a00, 0x000000012cd45600, 0x000000012cd54400, 0x000000012a190000,
0x00000001189e6600, 0x00000001189d0000, 0x00000001189d0600, 0x00000001189d0c00,
0x0000000118a03200, 0x000000012a14da00, 0x000000012b19bc00, 0x000000012b19c200,
0x000000012d831e00, 0x000000012d832400, 0x000000012d832a00, 0x000000012d833000,
0x000000012d833600, 0x000000012d833c00, 0x000000012b19c800, 0x000000012b1bc000,
0x000000012d80a000, 0x000000012cd82600, 0x000000012a1b4000, 0x000000011800a000,
0x000000012b80fc00, 0x000000011f008200, 0x0000000118809800, 0x000000012a1b4e00,
0x00000001189d8600, 0x0000000119040400, 0x0000000119047800
}

"Reference Handler" #2 daemon prio=10 os_prio=31 cpu=4.51ms elapsed=705.78s tid=0x000000012d029600 nid=0x4703 waiting on condition  [0x000000016ee5a000]
   java.lang.Thread.State: RUNNABLE
	at java.lang.ref.Reference.waitForReferencePendingList([email protected]/Native Method)
	at java.lang.ref.Reference.processPendingReferences([email protected]/Reference.java:253)
	at java.lang.ref.Reference$ReferenceHandler.run([email protected]/Reference.java:215)

"Finalizer" #3 daemon prio=8 os_prio=31 cpu=0.13ms elapsed=705.78s tid=0x000000012d02be00 nid=0x4603 in Object.wait()  [0x000000016f066000]
   java.lang.Thread.State: WAITING (on object monitor)
	at java.lang.Object.wait([email protected]/Native Method)
	- waiting on <0x0000000700337f28> (a java.lang.ref.ReferenceQueue$Lock)
	at java.lang.ref.ReferenceQueue.remove([email protected]/ReferenceQueue.java:155)
	- locked <0x0000000700337f28> (a java.lang.ref.ReferenceQueue$Lock)
	at java.lang.ref.ReferenceQueue.remove([email protected]/ReferenceQueue.java:176)
	at java.lang.ref.Finalizer$FinalizerThread.run([email protected]/Finalizer.java:172)

"Signal Dispatcher" #4 daemon prio=9 os_prio=31 cpu=0.09ms elapsed=705.77s tid=0x000000012b052c00 nid=0x7a03 waiting on condition  [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Service Thread" #5 daemon prio=9 os_prio=31 cpu=1.67ms elapsed=705.77s tid=0x000000012d80c200 nid=0x7803 runnable  [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Monitor Deflation Thread" #6 daemon prio=9 os_prio=31 cpu=7.28ms elapsed=705.77s tid=0x000000012d029c00 nid=0x5b03 runnable  [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C1 CompilerThread0" #7 daemon prio=9 os_prio=31 cpu=709.37ms elapsed=705.77s tid=0x0000000118808200 nid=0x5d03 waiting on condition  [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE
   No compile task

"Sweeper thread" #11 daemon prio=9 os_prio=31 cpu=2.18ms elapsed=705.77s tid=0x000000012d80c800 nid=0x7603 runnable  [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Common-Cleaner" #12 daemon prio=8 os_prio=31 cpu=3.61ms elapsed=705.76s tid=0x000000012a010400 nid=0x5e03 in Object.wait()  [0x000000016fdc6000]
   java.lang.Thread.State: TIMED_WAITING (on object monitor)
	at java.lang.Object.wait([email protected]/Native Method)
	- waiting on <0x0000000700330278> (a java.lang.ref.ReferenceQueue$Lock)
	at java.lang.ref.ReferenceQueue.remove([email protected]/ReferenceQueue.java:155)
	- locked <0x0000000700330278> (a java.lang.ref.ReferenceQueue$Lock)
	at jdk.internal.ref.CleanerImpl.run([email protected]/CleanerImpl.java:140)
	at java.lang.Thread.run([email protected]/Thread.java:833)
	at jdk.internal.misc.InnocuousThread.run([email protected]/InnocuousThread.java:162)

"Monitor Ctrl-Break" #13 daemon prio=5 os_prio=31 cpu=13.07ms elapsed=705.65s tid=0x000000012c808200 nid=0x5f03 runnable  [0x000000016ffd2000]
   java.lang.Thread.State: RUNNABLE
	at sun.nio.ch.SocketDispatcher.read0([email protected]/Native Method)
	at sun.nio.ch.SocketDispatcher.read([email protected]/SocketDispatcher.java:47)
	at sun.nio.ch.NioSocketImpl.tryRead([email protected]/NioSocketImpl.java:261)
	at sun.nio.ch.NioSocketImpl.implRead([email protected]/NioSocketImpl.java:312)
	at sun.nio.ch.NioSocketImpl.read([email protected]/NioSocketImpl.java:350)
	at sun.nio.ch.NioSocketImpl$1.read([email protected]/NioSocketImpl.java:803)
	at java.net.Socket$SocketInputStream.read([email protected]/Socket.java:966)
	at sun.nio.cs.StreamDecoder.readBytes([email protected]/StreamDecoder.java:270)
	at sun.nio.cs.StreamDecoder.implRead([email protected]/StreamDecoder.java:313)
	at sun.nio.cs.StreamDecoder.read([email protected]/StreamDecoder.java:188)
	- locked <0x000000070032ea28> (a java.io.InputStreamReader)
	at java.io.InputStreamReader.read([email protected]/InputStreamReader.java:177)
	at java.io.BufferedReader.fill([email protected]/BufferedReader.java:162)
	at java.io.BufferedReader.readLine([email protected]/BufferedReader.java:329)
	- locked <0x000000070032ea28> (a java.io.InputStreamReader)
	at java.io.BufferedReader.readLine([email protected]/BufferedReader.java:396)
	at com.intellij.rt.execution.application.AppMainV2$1.run(AppMainV2.java:31)

"Notification Thread" #14 daemon prio=9 os_prio=31 cpu=5.36ms elapsed=705.65s tid=0x000000012c897000 nid=0x6103 runnable  [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"RMI TCP Accept-0" #16 daemon prio=5 os_prio=31 cpu=9.27ms elapsed=705.38s tid=0x000000012b04fe00 nid=0x7303 runnable  [0x00000001703ea000]
   java.lang.Thread.State: RUNNABLE
	at sun.nio.ch.Net.accept([email protected]/Native Method)
	at sun.nio.ch.NioSocketImpl.accept([email protected]/NioSocketImpl.java:755)
	at java.net.ServerSocket.implAccept([email protected]/ServerSocket.java:675)
	at java.net.ServerSocket.platformImplAccept([email protected]/ServerSocket.java:641)
	at java.net.ServerSocket.implAccept([email protected]/ServerSocket.java:617)
	at java.net.ServerSocket.implAccept([email protected]/ServerSocket.java:574)
	at java.net.ServerSocket.accept([email protected]/ServerSocket.java:532)
	at sun.management.jmxremote.LocalRMIServerSocketFactory$1.accept([email protected]/LocalRMIServerSocketFactory.java:52)
	at sun.rmi.transport.tcp.TCPTransport$AcceptLoop.executeAcceptLoop([email protected]/TCPTransport.java:413)
	at sun.rmi.transport.tcp.TCPTransport$AcceptLoop.run([email protected]/TCPTransport.java:377)
	at java.lang.Thread.run([email protected]/Thread.java:833)

"Attach Listener" #20 daemon prio=9 os_prio=31 cpu=3.94ms elapsed=704.77s tid=0x000000012a011a00 nid=0x6b0b waiting on condition  [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"RMI Scheduler(0)" #22 daemon prio=5 os_prio=31 cpu=1.17ms elapsed=704.65s tid=0x000000012a190a00 nid=0xa203 waiting on condition  [0x000000017229e000]
   java.lang.Thread.State: TIMED_WAITING (parking)
	at jdk.internal.misc.Unsafe.park([email protected]/Native Method)
	- parking to wait for  <0x0000000700150f20> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
	at java.util.concurrent.locks.LockSupport.parkNanos([email protected]/LockSupport.java:252)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos([email protected]/AbstractQueuedSynchronizer.java:1672)
	at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take([email protected]/ScheduledThreadPoolExecutor.java:1182)
	at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take([email protected]/ScheduledThreadPoolExecutor.java:899)
	at java.util.concurrent.ThreadPoolExecutor.getTask([email protected]/ThreadPoolExecutor.java:1062)
	at java.util.concurrent.ThreadPoolExecutor.runWorker([email protected]/ThreadPoolExecutor.java:1122)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run([email protected]/ThreadPoolExecutor.java:635)
	at java.lang.Thread.run([email protected]/Thread.java:833)



qtp459249162-36" #36 prio=5 os_prio=31 cpu=42171.09ms elapsed=44.37s tid=0x000000010e8df400 nid=0x9103 runnable  [0x0000000175e60000]
   java.lang.Thread.State: RUNNABLE
	at org.eclipse.jetty.ee11.servlet.ServletContextResponse.getServletContextResponse(ServletContextResponse.java:77)
	at org.eclipse.jetty.ee11.servlet.ServletCoreResponse.<init>(ServletCoreResponse.java:62)
	at org.eclipse.jetty.ee11.servlet.ServletCoreResponse.wrap(ServletCoreResponse.java:48)
	at org.eclipse.jetty.ee11.websocket.servlet.WebSocketUpgradeFilter.doFilter(WebSocketUpgradeFilter.java:165)
	at org.eclipse.jetty.ee11.servlet.FilterHolder.doFilter(FilterHolder.java:205)
	at org.eclipse.jetty.ee11.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1640)
	at org.springframework.web.filter.CompositeFilter$VirtualFilterChain.doFilter(CompositeFilter.java:108)
	at org.springframework.security.web.FilterChainProxy.lambda$doFilterInternal$3(FilterChainProxy.java:235)
	at org.springframework.security.web.FilterChainProxy$$Lambda$2261/0x0000007001aba938.doFilter(Unknown Source)
	at org.springframework.security.web.ObservationFilterChainDecorator$FilterObservation$SimpleFilterObservation.lambda$wrap$1(ObservationFilterChainDecorator.java:493)
	at org.springframework.security.web.ObservationFilterChainDecorator$FilterObservation$SimpleFilterObservation$$Lambda$2286/0x0000007001ace9a8.doFilter(Unknown Source)
	at org.springframework.security.web.ObservationFilterChainDecorator$AroundFilterObservation$SimpleAroundFilterObservation.lambda$wrap$1(ObservationFilterChainDecorator.java:354)
	at org.springframework.security.web.ObservationFilterChainDecorator$AroundFilterObservation$SimpleAroundFilterObservation$$Lambda$2287/0x0000007001acebd0.doFilter(Unknown Source)
	at org.springframework.security.web.ObservationFilterChainDecorator.lambda$wrapSecured$0(ObservationFilterChainDecorator.java:86)
	at org.springframework.security.web.ObservationFilterChainDecorator$$Lambda$2262/0x0000007001abad88.doFilter(Unknown Source)
	at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:132)
	at org.springframework.security.web.access.intercept.AuthorizationFilter.doFilter(AuthorizationFilter.java:101)
	at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:244)
	at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:231)
	at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:141)
	at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:126)
	at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:120)
	at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:244)
	at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:231)
	at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:141)
	at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:132)
	at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:86)
	at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:244)
	at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:231)
	at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:141)
	at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:100)
	at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:244)
	at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:231)
	at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:141)
	at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:181)
	at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:244)
	at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:231)
	at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:141)
	at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63)
	at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:244)
	at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:231)
	at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:141)

From the last part of log it seems that thread is waiting on WebSocketUpgradeFilter.java ( at org.eclipse.jetty.ee11.websocket.servlet.WebSocketUpgradeFilter.doFilter(WebSocketUpgradeFilter.java:165)). Now we dont have any use case of using web socket and we are not enabling them by default.

Solution that worked for us :
On adding this bean definition I was able to bypass WebsocketUpgradeFilter and the problem was mitigated

@Bean(name = "websocketUpgradeFilterWebServerCustomizer")
    public WebServerFactoryCustomizer<JettyServletWebServerFactory> websocketUpgradeFilterWebServerCustomizer() {
        return factory -> {
            // INTENTIONALLY EMPTY: Do not register the WebSocketUpgradeFilter.
        };
    }

Even though it unblocked us and we could move forward and complete the spring boot 4 upgrade, but this seems like path instead of a proper solution. Can you guys look into it and explain the reason behind this deadlock situation?
How to reproduce?
Already explained above. Its not intermittent. The problem was happening every time we hit any Rest Endpoint

Metadata

Metadata

Assignees

Labels

BugFor general bugs on Jetty side

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions