[
https://issues.apache.org/jira/browse/CAMEL-24092?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Federico Mariani updated CAMEL-24092:
-------------------------------------
Attachment: FileLockReadLockIOExceptionShouldNotAcquireIssueTest.java
> camel-file: readLock=fileLock claims the lock after an IOException - file
> processed with no lock held and marker file deleted (possible duplicate
> consumption)
> --------------------------------------------------------------------------------------------------------------------------------------------------------------
>
> Key: CAMEL-24092
> URL: https://issues.apache.org/jira/browse/CAMEL-24092
> Project: Camel
> Issue Type: Bug
> Components: camel-file
> Affects Versions: 4.21.0
> Reporter: Federico Mariani
> Priority: Major
> Labels: code-review
> Attachments: FileLockReadLockIOExceptionShouldNotAcquireIssueTest.java
>
>
> h3. Problem
> In {{FileLockExclusiveReadLockStrategy.acquireExclusiveReadLock}}
> (FileLockExclusiveReadLockStrategy.java:114-140), with the default
> {{readLockTimeout=10000}}: if {{new RandomAccessFile(target, "rw")}} or
> {{channel.tryLock()}} throws {{IOException}} (file deleted between poll and
> lock, permission error, Windows AV/MS-Office special locks),
> {{handleIOException}} logs "Cannot acquire read lock. Will try again.",
> sleeps once, returns false - and control *falls out of the catch block*: the
> {{finally}} (since {{exclusive == false}}) closes channel/RAF and calls
> {{super.releaseExclusiveReadLockOnAbort(...)}} which *deletes the .camelLock
> marker file*, then the method stores {{lock = null}} and *returns true*.
> h3. Failure scenario
> The consumer processes the file with (a) no OS file lock and (b) the marker
> protection removed - a competing consumer in another JVM watching the same
> directory can acquire the marker and process the same file concurrently ->
> duplicate consumption. There is also no actual retry despite the "Will try
> again" log, and the {{timeout == 0}} branch correctly returns false - the two
> branches contradict each other.
> h3. History
> The fall-through-to-true dates to CAMEL-1195 (2008, deliberate "process
> anyway on Windows-AV IOE" degradation). But CAMEL-5324 (2012) later layered
> marker files into this strategy, and the finally releasing that marker before
> returning true cannot be intentional - it silently drops the exact cross-JVM
> protection CAMEL-5324 added. CAMEL-7988 changed the {{timeout==0}} branch
> from throw to return-false, leaving the branches contradictory.
> h3. Suggested fix
> Return false from the IOException path (consistent with the {{timeout==0}}
> branch). If the degraded consume-anyway behavior must be preserved for the
> Windows-AV case, at minimum the marker must not be released and the retry log
> fixed.
> Adjacent nit found in the same class: {{doReleaseExclusiveReadLock}} (line
> 164-165) fetches the {{RandomAccessFile}} under the
> {{FILE_LOCK_EXCLUSIVE_LOCK}} key instead of {{FILE_LOCK_RANDOM_ACCESS_FILE}},
> so {{rac}} is always null (no fd leak today only because closing the channel
> closes the shared fd).
> h3. Reproducer
> Attached failing JUnit test (place in
> {{core/camel-core/src/test/java/org/apache/camel/component/file/strategy/}},
> where the file component tests live). Makes the target file unwritable so
> {{RandomAccessFile("rw")}} throws, and asserts {{acquireExclusiveReadLock}}
> returns false; on current main it returns true (and has deleted the marker).
> ----
> _This issue was researched and filed by Claude Code on behalf of [~croway]
> (GitHub: Croway), as part of a deep code review of camel-file and camel-ftp.
> A failing JUnit reproducer is attached; it fails deterministically on current
> main (4.22.0-SNAPSHOT)._
--
This message was sent by Atlassian Jira
(v8.20.10#820010)