-
Bug
-
Resolution: Done
-
Major
-
2.2.2
-
None
It should be possible to call setTriggering(false) in the IF clause or, even, the BIND clause of a rule in order to switch off recursive triggering. This is sometimes necessary in order to avoid recursive triggering either in later BIND expressions or in another subexpression forming part of the IF condition. This is not currently possible for two reasons.
The first problem is simple. setTriggering is void and there is no way to call a void function when intiialising a BIND var or evaluating an IF condition. This can be remedied by modifying it to return a boolean. Luckily this change will not also break backwards compatibility.
The second problem is more subtle and only applies to interpreted rules. If the target method for a rule ends up being called during interpretation of expressions in the rule body then there is a danger of entering an infinite regression of triggering leading to stack overflow. Byteman normally avoids this by disabling triggering when the interpreter is operating. However, when that expression is a method call Byteman normally re-enables triggers and then makes a reflective call to invoke the method.
Rules can call setTriggering(false) to avoid this re-enabling of triggers. This is necessary when the rule needs to call the trigger method either directly or via some intermediate call path. The problem arises because execution of setTriggering itself requires a method invocation. Reflective execution requires invocation of various bits of Java code e.g. iterating over the supplied arguments. If the trigger method is one of those bits of Java code then the recursive trigger will occur before setTriggering gets executed.
The solution of this is to have the rule interpreter recognise a call to builtin method setTriggering as a special case and call it directly rather than by reflection.