Andrea Cosentino created CAMEL-24242:
----------------------------------------

             Summary: camel-aws2-athena: thread interruption during query 
polling is ignored, causing a busy poll loop
                 Key: CAMEL-24242
                 URL: https://issues.apache.org/jira/browse/CAMEL-24242
             Project: Camel
          Issue Type: Bug
          Components: camel-aws
            Reporter: Andrea Cosentino


h3. Problem

{{Athena2QueryHelper}} has an {{interrupted}} flag that gates both 
{{shouldAttempt()}} and {{shouldWait()}}:

{code:java}
if (this.interrupted) {
    LOG.trace("AWS Athena start query execution thread was interrupted, will 
try no more");
    return false;
}
{code}

The flag is *never assigned* anywhere in the class. It is read at 
{{Athena2QueryHelper}} lines 113 and 146 (and by the getter at line 459) but 
has no writer, so it is permanently {{false}} and both guards are dead code.

h3. How it regressed

CAMEL-20297 ("camel-aws2-athena: do not swallow interrupted exceptions", commit 
9e17300779) deliberately added interrupt handling in {{doWait()}}:

{code:java}
try {
    Thread.sleep(this.currentDelay);
} catch (InterruptedException e) {
    this.interrupted = Thread.interrupted(); // store, then clear, interrupt 
status
    LOG.trace("...wait thread was interrupted; will return at earliest 
opportunity");
    Thread.currentThread().interrupt();
}
{code}

CAMEL-22949 ("Migrate components from Thread.sleep() to Camel's Task API", 
commit 1b0fca17c0, PR #21215) replaced that block with 
{{Tasks.foregroundTask()...run(...)}} and dropped the {{catch}} clause -- which 
was the only writer of {{interrupted}}. The migration silently reverted 
CAMEL-20297.

h3. Impact

{{ForegroundTask.run()}} does restore the interrupt flag (ForegroundTask line 
124) and returns {{false}}, but {{doWait()}} discards the return value. So 
after the first interruption:

# the thread's interrupt flag stays set;
# {{shouldWait()}} still returns true because {{interrupted}} is false;
# the next {{doWait()}} hits {{Thread.sleep(initialDelay)}} inside 
{{ForegroundTask.run()}}, which throws {{InterruptedException}} *immediately* 
because the flag is set, and returns at once;
# the polling loop therefore spins with *no delay*, issuing 
{{GetQueryExecution}} calls as fast as the API allows, until {{waitTimeout}} 
elapses.

So an interrupt (for example during graceful shutdown or route stop) turns a 
well-behaved 2-second-interval poll into a tight busy loop against the AWS 
Athena API, for up to {{waitTimeout}} -- and up to {{maxAttempts x 
waitTimeout}} when {{resetWaitTimeoutOnRetry=true}}.

h3. Proposed fix

Capture the {{run()}} return value in {{doWait()}} and set {{interrupted}} when 
the task did not complete and the thread's interrupt status is set, restoring 
the CAMEL-20297 behaviour on top of the Task API.

h3. Affected versions

* {{main}} / 4.22.0 -- affected
* {{camel-4.18.x}} -- affected (carries the CAMEL-22949 migration)
* {{camel-4.14.x}} -- *not* affected, still has the original {{Thread.sleep}} + 
interrupt handling

----
_Reported by Claude Code on behalf of acosentino, from an automated audit of 
the camel-aws components._



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to