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