Problem With ReentrantLock and return in rules

  • Platform information:
    Docker image openhab:2.2

I have copied the pattern (https://docs.openhab.org/configuration/rules-dsl.html#concurrency-guard) of using locks in rules as I am updating multiple numbers and need the updates to be protected by a lock. the logic in the code is easier to write if we validate the conditions first and return if the conditions are not met. I’ve noticed that if I return from a rule the finally block is not executed. For locks this is bad and stops the rules associated with the lock from executing.

I have reproduced with the simplest config I could find.

Test.items:
Switch testswitch1

Test.rules:
import java.util.concurrent.locks.ReentrantLock

var ReentrantLock lock  = new ReentrantLock()

rule "Test Lock unlock"
when
    Item testswitch1 changed 
then
    logInfo("Test","TRYLOCKED")
    lock.lock()
    logInfo("Test","LOCKED")
    try {
        logInfo("Test","RETURN")
        return
    }  catch(Throwable t) {
        lock.unlock()
        logInfo("Test","catch:UNLOCKED")
    } finally{
        lock.unlock()
        logInfo("Test","finally:UNLOCKED")
    }
end

and a simple sitemap to toggle the switch:

sitemap default label="Home"
{
	Default item=testswitch1 label="Amazing button"
}

If you toggle the switch you see the following in the logs and never see UNLOCKED printed

2018-03-04 18:34:49.686 [DEBUG] [ntime.internal.engine.RuleEngineImpl] - Executing rule 'Test Lock unlock'
2018-03-04 18:34:49.788 [INFO ] [.eclipse.smarthome.model.script.Test] - TRYLOCKED
2018-03-04 18:34:49.791 [INFO ] [.eclipse.smarthome.model.script.Test] - LOCKED
2018-03-04 18:34:49.793 [INFO ] [.eclipse.smarthome.model.script.Test] - RETURN

Should this unlock the lock? Is this a bug or am I doing something stupid?

Thanks

Garth

I’ve seen this before too. In the Rules DSL I don’t think we can guarantee that the finally block will execute.

Rather than using return you can:

  • reorganize your code to not need the return
  • throw an exception instead of using return; the exception will be caught by the catch and the lock unlocked

I think this is a problem with Xtext/Xbase and not something that is implemented in the Rules DSL itself, though that is just a guess based on observation and not based on actually looking at the code.

One thing though you should try is using a ; after the return. The return statement is one that sometimes requires a semicolon to avoid some weird behavior.

return;

I’m not hopeful but it is worth a try.

1 Like

OK Thanks for the answer.

I tried to have a look at the Xtext/Xbase code but Java is definitely not my primary language and I wasn’t sure where to start as it is spread over multiple projects. (If any one can point to a rough place to start I can have a second go)

The semi colon didn’t help so I now throw an exception in the code now and catch and unlock.

The fact that there is no guarantee that the finally block will execute make me very wary of this rule language.

This should definitely be documented in big red letters or the feature removed.

The more I use the rule language the more I fine it weird, surprising and unpleasant to use. I may have to look into JSR223 scripting.

1 Like