Skip to content

Potential connection starvation due to DiscardPolicy usage in addConnectionExecutor #2378

Description

@QiuYucheng2003

I have analyzed the source code of HikariPool.java and identified a potential issue related to the thread pool configuration for addConnectionExecutor.

The addConnectionExecutor is responsible for creating new physical connections and adding them to the pool. Currently, it is configured with a CustomDiscardPolicy (which behaves similarly to DiscardPolicy).

Location
File: src/main/java/com/zaxxer/hikari/pool/HikariPool.java
Line: 118 (in the constructor)
Code:
this.addConnectionExecutor = createThreadPoolExecutor(maxPoolSize, poolName + ":connection-adder", threadFactory, new CustomDiscardPolicy());

Analysis In a high-concurrency scenario, if the addConnectionExecutor queue becomes full, the CustomDiscardPolicy will silently drop new PoolEntryCreator tasks.

Although addBagItem (line 412) attempts to check the queue size (if (waiting > addConnectionExecutor.getQueue().size())), a race condition or a sudden spike in requests could still result in the task submission being rejected by the policy.

If the task is discarded:

  1. No new connection is created.
  2. Threads waiting in connectionBag.borrow() will continue to wait until they timeout (SQLTransientConnectionException).
  3. The pool fails to expand to maximumPoolSize even though the database might be healthy.

This fits the DenyPolicySettingError (DPSE) pattern, where using a discard policy for critical resource production tasks leads to silent failures and resource starvation.

Suggested Fix Consider changing the rejection policy to CallerRunsPolicy or ensuring that the CustomDiscardPolicy provides a fallback mechanism (e.g., logging a warning or retrying) rather than silently ignoring the request.

Using CallerRunsPolicy would ensure that if the executor is busy, the calling thread (which is likely waiting for a connection anyway) assists in creating the connection, thus preventing task loss.
// Suggested change:
this.addConnectionExecutor = createThreadPoolExecutor(maxPoolSize, poolName + ":connection-adder", threadFactory, new ThreadPoolExecutor.CallerRunsPolicy());

Environment
HikariCP version: (Master)
JDK version: 1.8

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions