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)