Open eclipse-qvt-oml-bot opened 5 hours ago
By Dennis Hendriks on Jun 15, 2016 09:28
Created attachment 262459 Example QVTo transformation to show the issue
This is an example QVTo transformation to show the issue. Note that the first iteration of the 'forEach' does result in 'aa' being added to the list. After that, the 'forEach' is not executed further, but the 'log' statement after that is executed. The output is as follows:
[output] test1, data: [a, b, c] test2, data: [a, b, c, aa] [/output]
I think QVTo should either make sure execution does not result in a CME, or fail the entire transformation when the CME occurs. I don't know what the QVT specification says about the semantics here. However, QVTo should definitely not continue execution after such a crash.
:notepad_spiral: test_cme.qvto
By Ed Willink on Jun 15, 2016 10:08
(In reply to Dennis Hendriks from comment #1)
I don't know what the QVT specification says about the semantics here.
8.2.2.6 ForExp: A for expression is an imperative loop expression that iterates over a source collection ... When applying the for expression, if the source collection is not ordered it is implicitly converted into the corresponding ordered collection
This seems to have a clear intent to iterate over an appropriate immutable OCL Collection.
Therefore the Java code must create a copy of the list prior to the iteration, unless it analyses the loop body and all its transitive virtual calls to prove that the list is not modified.
However, QVTo should definitely not continue execution after such a crash.
Yes. But a different issue.
By Dennis Hendriks on Jun 16, 2016 03:17
(In reply to Ed Willink from comment #2)
However, QVTo should definitely not continue execution after such a crash.
Yes. But a different issue.
Will you create a separate bug for that?
| --- | --- | | Bugzilla Link | 496178 | | Status | UNCONFIRMED | | Importance | P3 normal | | Reported | Jun 15, 2016 09:25 EDT | | Modified | Jun 16, 2016 03:17 EDT | | Reporter | Dennis Hendriks |
Description
When modifying a 'List' inside a 'forEach' over that 'List', a java.util.ConcurrentModificationException occurs. QVTo stops executing the remainder of the 'forEach', but does continue with the next statement. In the end, execution of the transformation 'succeeds', and the CME is logged to the Eclipse Error log.
The following is logged:
[log]\ Evaluation failed at 'test_cme.qvto:6' with a reason: ConcurrentModificationException. Expression yields an 'invalid' value.
java.util.ConcurrentModificationException\ at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:819)\ at java.util.ArrayList$Itr.next(ArrayList.java:791)\ at org.eclipse.m2m.internal.qvt.oml.evaluator.iterators.QvtIterationTemplate.advanceIterators(QvtIterationTemplate.java:159)\ at org.eclipse.m2m.internal.qvt.oml.evaluator.iterators.QvtIterationTemplate.evaluate(QvtIterationTemplate.java:119)\ at org.eclipse.m2m.internal.qvt.oml.evaluator.QvtOperationalEvaluationVisitorImpl.visitForExp(QvtOperationalEvaluationVisitorImpl.java:1500)\ at org.eclipse.m2m.internal.qvt.oml.evaluator.QvtGenericEvaluationVisitor.visitForExp(QvtGenericEvaluationVisitor.java:446)\ at org.eclipse.m2m.qvt.oml.ecore.ImperativeOCL.impl.ForExpImpl.accept(ForExpImpl.java:59)\ at org.eclipse.m2m.internal.qvt.oml.evaluator.QvtOperationalEvaluationVisitorImpl.visitExpression(QvtOperationalEvaluationVisitorImpl.java:419)\ at org.eclipse.m2m.internal.qvt.oml.evaluator.QvtOperationalEvaluationVisitorImpl.visitOperationBody(QvtOperationalEvaluationVisitorImpl.java:1169)\ at org.eclipse.m2m.internal.qvt.oml.evaluator.QvtOperationalEvaluationVisitorImpl.visitEntryOperation(QvtOperationalEvaluationVisitorImpl.java:496)\ at org.eclipse.m2m.internal.qvt.oml.evaluator.QvtGenericEvaluationVisitor.visitEntryOperation(QvtGenericEvaluationVisitor.java:461)\ at org.eclipse.m2m.internal.qvt.oml.expressions.impl.EntryOperationImpl.accept(EntryOperationImpl.java:67)\ at org.eclipse.m2m.internal.qvt.oml.evaluator.QvtOperationalEvaluationVisitorImpl.executeImperativeOperation(QvtOperationalEvaluationVisitorImpl.java:1968)\ at org.eclipse.m2m.internal.qvt.oml.evaluator.QvtOperationalEvaluationVisitorImpl.runMainEntry(QvtOperationalEvaluationVisitorImpl.java:2569)\ at org.eclipse.m2m.internal.qvt.oml.evaluator.QvtOperationalEvaluationVisitorImpl$1.invoke(QvtOperationalEvaluationVisitorImpl.java:1070)\ at org.eclipse.m2m.internal.qvt.oml.evaluator.QvtOperationalEvaluationVisitorImpl$1.invoke(QvtOperationalEvaluationVisitorImpl.java:1)\ at org.eclipse.m2m.internal.qvt.oml.evaluator.QvtOperationalEvaluationVisitorImpl.doVisitTransformation(QvtOperationalEvaluationVisitorImpl.java:1096)\ at org.eclipse.m2m.internal.qvt.oml.evaluator.QvtOperationalEvaluationVisitorImpl.visitModule(QvtOperationalEvaluationVisitorImpl.java:878)\ at org.eclipse.m2m.internal.qvt.oml.evaluator.QvtGenericEvaluationVisitor.visitModule(QvtGenericEvaluationVisitor.java:372)\ at org.eclipse.m2m.internal.qvt.oml.expressions.impl.ModuleImpl.accept(ModuleImpl.java:632)\ at org.eclipse.m2m.internal.qvt.oml.runtime.project.QvtInterpretedTransformation.evaluate(QvtInterpretedTransformation.java:185)\ at org.eclipse.m2m.internal.qvt.oml.runtime.project.QvtInterpretedTransformation.run(QvtInterpretedTransformation.java:118)\ at org.eclipse.m2m.internal.qvt.oml.runtime.launch.QvtLaunchConfigurationDelegateBase.doLaunch(QvtLaunchConfigurationDelegateBase.java:194)\ at org.eclipse.m2m.internal.qvt.oml.runtime.launch.QvtLaunchConfigurationDelegateBase.doLaunch(QvtLaunchConfigurationDelegateBase.java:154)\ at org.eclipse.m2m.internal.qvt.oml.runtime.launch.QvtLaunchConfigurationDelegate$1.run(QvtLaunchConfigurationDelegate.java:65)\ at org.eclipse.m2m.internal.qvt.oml.common.launch.SafeRunner$SameThreadRunner.run(SafeRunner.java:33)\ at org.eclipse.m2m.internal.qvt.oml.common.launch.SafeRunner$1.run(SafeRunner.java:26)\ at org.eclipse.m2m.internal.qvt.oml.common.launch.ShallowProcess.run(ShallowProcess.java:45)\ at org.eclipse.m2m.internal.qvt.oml.common.launch.ShallowProcess.run(ShallowProcess.java:36)\ at org.eclipse.m2m.internal.qvt.oml.runtime.launch.QvtLaunchConfigurationDelegate$3.run(QvtLaunchConfigurationDelegate.java:100)\ at java.lang.Thread.run(Thread.java:722)
[/log]