[Bug] (fe) Client disconnect causes orphaned query hung in active_queries and leaks workload group queue slots
Search before asking
- I had searched in the issues and found no similar issues.
Version
3.0.x / 4.1.x / master
What's Wrong?
When a client application (e.g., a microservice or web backend with a 3–5 second query timeout) disconnects due to client-side timeout while the query is still waiting on the BE (e.g. waiting for rowset/delete-bitmap lock or waiting in queue during heavy ingestion/compaction), the following cascade failure occurs:
FE Network Layer Removes Connection Silently: FE's
AcceptListenerdetects the TCP FIN/RST from the client and triggersconnection.setCloseListener(...)->connectScheduler.getConnectPoolMgr().unregisterConnection(context). The connection is removed fromconnectionMap.No Cancel Signal Is Dispatched:
ConnectPoolMgr.unregisterConnection()removes the context fromconnectionMap, but does NOT callcontext.cancelQuery(). No cancel signal is sent to theCoordinator, and nocancel_plan_fragmentRPC is dispatched to BE nodes.Query Escapes
TimeoutCheckerEntirely (Ghost Query): FE's backgroundTimeoutChecker(checkTimer) iterates strictly overconnectionMap.values(). Because the connection was already removed in step 1,checkTimeout()is never called again for this context. The query bypassesquery_timeout(e.g. 300s) and hangs indefinitely inQeProcessorImpl/information_schema.active_queries(observed running for >3400 seconds / 57 minutes asRUNNING).FE Worker Thread Stalls in
coordBase.getNext(): Because the query was actively executing andReadListener.suspendAcceptQuery()had already suspended reading on the socket, the worker thread remains blocked waiting for BE results. Since no data is written to the closed socket, noIOException/EPIPEis raised to break the loop.Workload Group Queue Slot Leak & Cluster Stall: Because
Coordinator.close()is never executed, the query'sQueueTokenis never returned to theQueryQueue. When all slots (max_concurrency) in the workload group are occupied by these orphaned queries, all subsequent queries in that workload group are stuck inWAIT_IN_QUEUEforever, until they fail withquery queue timeout.
What You Expected?
When a client disconnects or closes the connection:
unregisterConnection()must immediately cancel any active query on that connection.- The
Coordinatormust abort BE fragment execution via cancel RPCs, release the workload group'sQueueToken, and unblock the worker thread. - The query must be immediately removed from
QeProcessorImplandinformation_schema.active_queries. - Workload group slots must be promptly freed for queued queries.
How to Reproduce?
- Create a workload group with strict concurrency:
CREATE WORKLOAD GROUP wg_test PROPERTIES ('max_concurrency'='1', 'max_queue_size'='10', 'queue_timeout'='60000'); - Assign
wg_testto usertest. - Submit a query that takes several seconds (or simulate a lock wait / slow scan on BE).
- Abruptly kill the client process (send TCP FIN/RST) within 2 seconds before any result row is returned.
- Inspect
information_schema.active_queries:- The query remains
RUNNINGlong afterquery_timeout.
- The query remains
- Submit a second query from a new connection:
- The new query stays in
WAIT_IN_QUEUEand eventually times out.
- The new query stays in
Anything Else?
Observed in production where point-lookups (SELECT ... FROM tbl WHERE user_id = ...) encountering lock wait were abandoned by client microservices after 3s. The orphaned queries lived for >57 minutes in active_queries while subsequent queries piled up in WAIT_IN_QUEUE.
Are you willing to submit PR?
- Yes I am willing to submit a PR!
Code of Conduct
- I agree to follow this project's Code of Conduct
Source: apache/doris