Luigi De Masi created CAMEL-19833:
-------------------------------------
Summary: camel-bindy - race condition in
BindyAbstractFactory.link()
Key: CAMEL-19833
URL: https://issues.apache.org/jira/browse/CAMEL-19833
Project: Camel
Issue Type: Improvement
Reporter: Luigi De Masi
org.apache.camel.dataformat.bindy.BindyAbstractFactory.link() calls
org.apache.camel.util.ReflectionHelper.setField() :
{noformat}
public static void setField(Field f, Object instance, Object value) {
try {
boolean oldAccessible = f.isAccessible();
boolean shouldSetAccessible = !Modifier.isPublic(f.getModifiers())
&& !oldAccessible;
if (shouldSetAccessible) {
f.setAccessible(true);
}
f.set(instance, value);
if (shouldSetAccessible) {
f.setAccessible(oldAccessible);
}
} catch (Exception ex) {
throw new UnsupportedOperationException("Cannot inject value of
class: " + value.getClass() + " into: " + f); // breakpoint
}
}
{noformat}
In a concurrent situation, access violation occurs due to race condition:
Thread A: invokes check the accessibility and set "shouldSetAccessible" to true.
Thread A: invokes f.setAccessible(true);
Thread B: invokes check the accessibility and set "shouldSetAccessible" to
false.
Thread A: invokes f.set(instance, value and f.setAccessible(oldAccessible);
Thread B: invokes f.set(instance, value); and java.lang.IllegalAccessException
occurs.
- Following exception will occur.
{noformat}
java.lang.UnsupportedOperationException: Cannot inject value of class: class
com.redhat.MyModel2 into: private com.redhat.MyModel2
com.redhat.MyModel.myModel2
at
org.apache.camel.util.ReflectionHelper.setField(ReflectionHelper.java:192)
at
org.apache.camel.dataformat.bindy.BindyAbstractFactory.link(BindyAbstractFactory.java:150)
at
org.apache.camel.dataformat.bindy.csv.BindyCsvDataFormat.lambda$consumeFile$0(BindyCsvDataFormat.java:263)
at java.base/java.util.Iterator.forEachRemaining(Iterator.java:133)
at
java.base/java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1845)
at
java.base/java.util.stream.ReferencePipeline$Head.forEachOrdered(ReferencePipeline.java:772)
at
org.apache.camel.dataformat.bindy.csv.BindyCsvDataFormat.unmarshal(BindyCsvDataFormat.java:183)
at
org.apache.camel.support.processor.UnmarshalProcessor.process(UnmarshalProcessor.java:76)
at
org.apache.camel.processor.errorhandler.RedeliveryErrorHandler$SimpleTask.run(RedeliveryErrorHandler.java:477)
at
org.apache.camel.impl.engine.DefaultReactiveExecutor$Worker.schedule(DefaultReactiveExecutor.java:181)
at
org.apache.camel.impl.engine.DefaultReactiveExecutor.schedule(DefaultReactiveExecutor.java:54)
at
org.apache.camel.processor.errorhandler.RedeliveryErrorHandler$SimpleTask.run(RedeliveryErrorHandler.java:482)
at
org.apache.camel.processor.errorhandler.RedeliveryErrorHandler$SimpleTask.done(RedeliveryErrorHandler.java:416)
at
org.apache.camel.processor.ThreadsProcessor$ProcessCall.run(ThreadsProcessor.java:87)
at
java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at
java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
at
java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
at java.base/java.lang.Thread.run(Thread.java:833)
{noformat}
core/camel-util/src/main/java/org/apache/camel/util/ReflectionHelper.java
{noformat}
public static void setField(Field f, Object instance, Object value) {
try {
boolean oldAccessible = f.isAccessible();
boolean shouldSetAccessible = !Modifier.isPublic(f.getModifiers())
&& !oldAccessible;
if (shouldSetAccessible) {
f.setAccessible(true);
}
f.set(instance, value);
if (shouldSetAccessible) {
f.setAccessible(oldAccessible);
}
} catch (Exception ex) {
throw new UnsupportedOperationException("Cannot inject value of
class: " + value.getClass() + " into: " + f); // breakpoint
}
}
{noformat}
Thread A: invokes check the accessibility and set "shouldSetAccessible" to true.
Thread A: invokes f.setAccessible(true);
Thread B: invokes check the accessibility and set "shouldSetAccessible" to
false.
Thread A: invokes f.set(instance, value and f.setAccessible(oldAccessible);
Thread B: invokes f.set(instance, value); and java.lang.IllegalAccessException
occurs.
- Following exception will occur.
{noformat}
java.lang.UnsupportedOperationException: Cannot inject value of class: class
com.redhat.MyModel2 into: private com.redhat.MyModel2
com.redhat.MyModel.myModel2
at
org.apache.camel.util.ReflectionHelper.setField(ReflectionHelper.java:192)
at
org.apache.camel.dataformat.bindy.BindyAbstractFactory.link(BindyAbstractFactory.java:150)
at
org.apache.camel.dataformat.bindy.csv.BindyCsvDataFormat.lambda$consumeFile$0(BindyCsvDataFormat.java:263)
at java.base/java.util.Iterator.forEachRemaining(Iterator.java:133)
at
java.base/java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1845)
at
java.base/java.util.stream.ReferencePipeline$Head.forEachOrdered(ReferencePipeline.java:772)
at
org.apache.camel.dataformat.bindy.csv.BindyCsvDataFormat.unmarshal(BindyCsvDataFormat.java:183)
at
org.apache.camel.support.processor.UnmarshalProcessor.process(UnmarshalProcessor.java:76)
at
org.apache.camel.processor.errorhandler.RedeliveryErrorHandler$SimpleTask.run(RedeliveryErrorHandler.java:477)
at
org.apache.camel.impl.engine.DefaultReactiveExecutor$Worker.schedule(DefaultReactiveExecutor.java:181)
at
org.apache.camel.impl.engine.DefaultReactiveExecutor.schedule(DefaultReactiveExecutor.java:54)
at
org.apache.camel.processor.errorhandler.RedeliveryErrorHandler$SimpleTask.run(RedeliveryErrorHandler.java:482)
at
org.apache.camel.processor.errorhandler.RedeliveryErrorHandler$SimpleTask.done(RedeliveryErrorHandler.java:416)
at
org.apache.camel.processor.ThreadsProcessor$ProcessCall.run(ThreadsProcessor.java:87)
at
java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at
java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
at
java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
at java.base/java.lang.Thread.run(Thread.java:833)
{noformat}
--
This message was sent by Atlassian Jira
(v8.20.10#820010)