I am running a DSL rule which is protected by an reentrant lock:
var ReentrantLock mylock = new ReentrantLock()
rule "Update"
when
Item Item1 changed or
Item Item2 changed
then
if (mylock.tryLock(0, TimeUnit.SECONDS)) {
try {
...
} catch(Throwable t) {
logError("Error", "Some bad stuff happened in my rule: " + T.toString)
} finally {
mylock.unlock()
}
} else {
logInfo("Rule", "Failed to lock!")
}
end
During startup I see
2025-06-29 16:44:13.725 [ERROR] [.handler.AbstractScriptModuleHandler] - Script execution of rule with UID 'rules-2' failed: The name mylock' cannot be resolved to an item or type; line 20, column 6, length 14 in rules
2025-06-29 16:44:16.177 [ERROR] [.handler.AbstractScriptModuleHandler] - Script execution of rule with UID rules-2' failed: null in rules
2025-06-29 16:44:27.108 [INFO ] [nhab.core.model.script.Rule] - Failed to lock!
so it can’t find the lock, still it manages to lock it and from then on it will no longer execute the rule as it is unable to lock again.
Is there any way I could workaround this apparently known issue, that global variables are not necessarily initialized before the rule is executed?
That’ll run much later than an initialization in the global declaration. But if your idea is to basically overwrite the locked/messed up lock on system start once and fix it this way, that might actually work. Thanks, I’ll try that.
At some point the rule engine must be fixed though, the whole startup is a mess. Rules executing on/before states are restored or before the rule engine itself is ready, that’s just looking for disaster.
In any version of OH after 2.5 there is no need to use reentrant locks on a rule. It is impossible for the same rule to be running more than one at a time so the reentrant lock is redundant at best and dangerous at worse if an error occurs that cannot be caught inside the rule and the lock never gets unlocked.
So this is an XY Problem. The real solution is to not use reentrant locks at all. They no longer serve any purpose. The rule is already locked.
If you need to prevent two rules from running at the same time it is almost always safer and easier to combine the two rules into one. If if the rule ends up being longer and it does more than one thing it will still be simpler and less brittle over using reentrant locks.
If using pretty much any of the other languages for rules, including simple managed rules and Blockly, you have the option to disable/enable other rules from a rule so you can disable the other rule while this one is running as the first action and then enable it when the rule is done.
Reentrant locks were never really safe to use in Rules DSL from the beginning. Some errors including common ones like type errors, never bubble back up to the rule, meaning you can’t catch them. When such locks were our only option, we had to use them. Now, they should not be used except in the most extreme circumstances, and even then an alternative approach is probably better. If you need locking, rely on the automatic locking that you get for free from the rule engine instead.