shashank created CAMEL-25003:
--------------------------------

             Summary: camel-core - ServicePool hands out a stopped 
non-singleton producer after LRU eviction, and stops producers in use
                 Key: CAMEL-25003
                 URL: https://issues.apache.org/jira/browse/CAMEL-25003
             Project: Camel
          Issue Type: Bug
          Components: camel-core
            Reporter: shashank


For endpoints whose producer is not a singleton ({{isSingletonProducer() == 
false}}: camel-ftp/sftp/ftps, camel-smb, camel-ssh, and the polling consumers 
used by pollEnrich), {{ServicePool}} keeps one {{MultiplePool}} per endpoint (a 
queue of idle producers). It also keeps an LRU cache, of size {{cacheSize}}, of 
every producer it handed out.

When the LRU evicts such a producer, {{onEvict}} only adds it to the pool's 
{{evicts}} list. The next {{acquire}} or {{release}} on that pool runs 
{{cleanupEvicts}}, which stops the producer. But cleanupEvicts does not take 
the producer out of the pool queue:
# If the producer was idle, the {{acquire}} that polls the queue right after 
{{cleanupEvicts}} hands it out, stopped.
# If the producer was in use by another exchange, it is stopped under that 
exchange. When that exchange releases it, {{release}} offers it back to the 
queue, and it is handed out again, stopped.

Any workload that uses more producer instances than {{cacheSize}} evicts 
producers that are idle in a queue or in use.

Reproduced against the real classes, using a test component whose producers are 
non-singleton and which records use after stop. With 
{{from("direct:in").toD("pooled:${header.to}", 2)}}, 4 threads and 2000 
exchanges to two endpoints:
{noformat}
created=222 stopped=222 usedAfterStop=1664 stopWhileInUse=1
{noformat}
1664 of 2000 exchanges were sent with a stopped producer.

Handing out a stopped producer is a regression from CAMEL-20829 (4.7), which 
removed the {{queue.remove(evict)}} from {{cleanupEvicts}}.

Found with a TLA+ model of ServicePool (pooled producers, LRU eviction, 
concurrent acquire/release). The invariants "never used after stop", "never 
stopped in use" and "queue holds only started producers" are violated.

Proposed fix, in {{ServicePool.MultiplePool}}:
* {{evict}} takes an idle producer out of the queue before it is stopped, and 
leaves a producer in use alone.
* {{release}} stops a producer that was evicted while in use, instead of 
offering it back to the queue.
* {{onEvict}} no longer stops a producer whose pool is gone. At that point the 
producer can only be in use, and {{release}} stops it, as it does since 
CAMEL-24248.

_Filed with Claude Code on behalf of allthingssecurity._




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

Reply via email to