Odd behavior using ReentrantLock

Not sure if this helps, but here you go:

  • I don’t see where you are actually setting your stop-switch
  • also the logic if(!lock_GZL.isLocked && Sonoff_STOP.state != ON) will fail if you never got a lock; and by fail I mean execute multiple times

The latter issue, simply not getting a lock in time, perplexed me quite a bit some a year or two ago, here is how I am structuring my rules

rule "MyRule"
when
  // trule triggers go here
then
	var gotLock = lock.tryLock(1000, TimeUnit.MILLISECONDS)	
	try {
		if (gotLock) {
                                      // do stuff here
		}		   
		else logInfo("MyRule", "re-entry lock activated")
	}
	finally {
		if(gotLock){
			lock.unlock()
		}
	} 
end

here are some additional considerations/explanations:

  • if it works you can probably get rid of your thread::sleep statements
  • see here for for some more details: Design Pattern: Rule Latching
  • this line: var gotLock = lock.tryLock(1000, TimeUnit.MILLISECONDS) makes the system essentially behave a little nicer (the value 1000 does not seem to matter, 0 will do too, see post linked above)
  • doing so you will simply drop events, but I guess that is exactly what you want; just stating this for clarity
  • now to the real problem:
    – in certain conditions your rule may die while in the try{} block and never execute the finally {} statement releasing the lock;
    – when this happens, your rule will never execute the try{} block again as the lock will still be set;
    – where this is becoming a real issue in my case is during start up where a rule may execute before items are defined or even the rule parser is fully up and running and I am seeing syntax errors that are not real syntax errors but some artefact during system start and Null pointer exceptions; when this happens the rule will abort and the lock will not be released.
    – if you apply one of the many tricks that will run your rules only after everything else started up well (e.g, “preferred version” from here: Cleaning up the startup process / renaming rules (windows possible)), it will however work like a charm.
    – Finally, be forewarned already in case you are reading the JAVA docs on concurrency guards, this whole mechanism of concurrency guard is implemented only implemented to a limited extent in the DSL; while JAVA offers here error catching and handling, this will not work well in DSL and not at all for NPE or syntax errors; (hence it is not implemented above); I tried… and others on the forum too, it is not worth the efforts as only very few errors are caught; you will need to take extra care in coding
3 Likes