import static org.openhab.core.automation.module.script.ScriptTransformationService.OPENHAB_TRANSFORMATION_SCRIPT;
import java.util.Arrays;
+import java.util.concurrent.locks.Lock;
import java.util.stream.Collectors;
import javax.script.Compilable;
* @author Jonathan Gilbert - Initial contribution
* @author Florian Hotze - Improve logger name, Fix memory leak caused by exception logging
*/
-class DebuggingGraalScriptEngine<T extends ScriptEngine & Invocable & AutoCloseable & Compilable>
+class DebuggingGraalScriptEngine<T extends ScriptEngine & Invocable & AutoCloseable & Compilable & Lock>
extends InvocationInterceptingScriptEngineWithInvocableAndCompilableAndAutoCloseable<T> {
private static final int STACK_TRACE_LENGTH = 5;
@Override
protected void beforeInvocation() {
super.beforeInvocation();
- if (logger == null) {
- initializeLogger();
+ // OpenhabGraalJSScriptEngine::beforeInvocation will be executed after
+ // DebuggingGraalScriptEngine::beforeInvocation, because GraalJSScriptEngineFactory::createScriptEngine returns
+ // a DebuggingGraalScriptEngine instance.
+ // We therefore need to synchronize logger setup here and cannot rely on the synchronization in
+ // OpenhabGraalJSScriptEngine.
+ delegate.lock();
+ try {
+ if (logger == null) {
+ initializeLogger();
+ }
+ } finally { // Make sure that Lock is unlocked regardless of an exception being thrown or not to avoid deadlocks
+ delegate.unlock();
}
}
import java.time.ZonedDateTime;
import java.util.Map;
import java.util.Set;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Consumer;
* {@link Lock} for multi-thread synchronization; globals and openhab-js injection code caching
*/
public class OpenhabGraalJSScriptEngine
- extends InvocationInterceptingScriptEngineWithInvocableAndCompilableAndAutoCloseable<GraalJSScriptEngine> {
+ extends InvocationInterceptingScriptEngineWithInvocableAndCompilableAndAutoCloseable<GraalJSScriptEngine>
+ implements Lock {
private static final Logger LOGGER = LoggerFactory.getLogger(OpenhabGraalJSScriptEngine.class);
private static final Source GLOBAL_SOURCE;
return new InputStreamReader(ioStream);
}
+
+ @Override
+ public void lock() {
+ lock.lock();
+ }
+
+ @Override
+ public void lockInterruptibly() throws InterruptedException {
+ lock.lockInterruptibly();
+ }
+
+ @Override
+ public boolean tryLock() {
+ return lock.tryLock();
+ }
+
+ @Override
+ public boolean tryLock(long l, TimeUnit timeUnit) throws InterruptedException {
+ return lock.tryLock(l, timeUnit);
+ }
+
+ @Override
+ public void unlock() {
+ lock.unlock();
+ }
+
+ @Override
+ public Condition newCondition() {
+ return lock.newCondition();
+ }
}