Fix deadlock when removing ScriptEngine (#2785)

Signed-off-by: Jan N. Klug <github@klug.nrw>
pull/2804/head
J-N-K 2022-02-26 10:29:38 +01:00 committed by GitHub
parent 013e317b6b
commit 0ba4de3594
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 17 additions and 6 deletions

View File

@ -20,6 +20,8 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import javax.script.Invocable;
import javax.script.ScriptContext;
@ -34,6 +36,7 @@ import org.openhab.core.automation.module.script.ScriptEngineContainer;
import org.openhab.core.automation.module.script.ScriptEngineFactory;
import org.openhab.core.automation.module.script.ScriptEngineManager;
import org.openhab.core.automation.module.script.ScriptExtensionManagerWrapper;
import org.openhab.core.common.ThreadPoolManager;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
@ -52,6 +55,9 @@ import org.slf4j.LoggerFactory;
@Component(service = ScriptEngineManager.class)
public class ScriptEngineManagerImpl implements ScriptEngineManager {
private final ScheduledExecutorService scheduler = ThreadPoolManager
.getScheduledPool(ThreadPoolManager.THREAD_POOL_NAME_COMMON);
private final Logger logger = LoggerFactory.getLogger(ScriptEngineManagerImpl.class);
private final Map<String, ScriptEngineContainer> loadedScriptEngineInstances = new HashMap<>();
private final Map<String, ScriptEngineFactory> customSupport = new HashMap<>();
@ -216,12 +222,17 @@ public class ScriptEngineManagerImpl implements ScriptEngineManager {
}
if (scriptEngine instanceof AutoCloseable) {
AutoCloseable closeable = (AutoCloseable) scriptEngine;
try {
closeable.close();
} catch (Exception e) {
logger.error("Error while closing script engine", e);
}
// we cannot not use ScheduledExecutorService.execute here as it might execute the task in the calling
// thread (calling ScriptEngine.close in the same thread may result in a deadlock if the ScriptEngine
// tries to Thread.join)
scheduler.schedule(() -> {
AutoCloseable closeable = (AutoCloseable) scriptEngine;
try {
closeable.close();
} catch (Exception e) {
logger.error("Error while closing script engine", e);
}
}, 0, TimeUnit.SECONDS);
} else {
logger.trace("ScriptEngine does not support AutoCloseable interface");
}