From 890dab49a40af6610050eab043be59ce9600d4ad Mon Sep 17 00:00:00 2001 From: Lukas Stadler <lukas.stadler@oracle.com> Date: Fri, 18 Aug 2017 17:03:00 +0200 Subject: [PATCH] clean up threads when shutting down context --- .../truffle/r/nodes/builtin/fastr/FastRContext.java | 6 +++--- .../src/com/oracle/truffle/r/runtime/RCleanUp.java | 10 ++++++++++ .../oracle/truffle/r/runtime/context/EvalThread.java | 12 +++++++----- .../oracle/truffle/r/runtime/context/RContext.java | 2 ++ 4 files changed, 22 insertions(+), 8 deletions(-) diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRContext.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRContext.java index d05f42daf1..1fec8cd3b2 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRContext.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRContext.java @@ -142,7 +142,7 @@ public class FastRContext { int[] multiSlotIndices = new int[length]; for (int i = 0; i < length; i++) { ChildContextInfo info = createContextInfo(contextKind); - threads[i] = new EvalThread(info, RSource.fromTextInternalInvisible(exprs.getDataAt(i % exprs.getLength()), RSource.Internal.CONTEXT_EVAL), + threads[i] = new EvalThread(RContext.getInstance().threads, info, RSource.fromTextInternalInvisible(exprs.getDataAt(i % exprs.getLength()), RSource.Internal.CONTEXT_EVAL), FastROptions.SpawnUsesPolyglot.getBooleanValue()); data[i] = info.getId(); multiSlotIndices[i] = info.getMultiSlotInd(); @@ -175,7 +175,7 @@ public class FastRContext { int[] multiSlotIndices = new int[handle.getLength()]; for (int i = 0; i < handle.getLength(); i++) { int id = handle.getDataAt(i); - Thread thread = EvalThread.threads.get(id); + Thread thread = RContext.getInstance().threads.get(id); if (EvalThread.idToMultiSlotTable.containsKey(id)) { multiSlotIndices[i] = EvalThread.idToMultiSlotTable.remove(id); } @@ -245,7 +245,7 @@ public class FastRContext { int[] multiSlotIndices = new int[length]; for (int i = 0; i < length; i++) { ChildContextInfo info = createContextInfo(contextKind); - threads[i] = new EvalThread(info, RSource.fromTextInternalInvisible(exprs.getDataAt(i % exprs.getLength()), RSource.Internal.CONTEXT_EVAL), false); + threads[i] = new EvalThread(RContext.getInstance().threads, info, RSource.fromTextInternalInvisible(exprs.getDataAt(i % exprs.getLength()), RSource.Internal.CONTEXT_EVAL), false); multiSlotIndices[i] = info.getMultiSlotInd(); } if (contextKind == ContextKind.SHARE_ALL) { diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCleanUp.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCleanUp.java index ff122d9ae2..d33648e88f 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCleanUp.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCleanUp.java @@ -101,6 +101,16 @@ public class RCleanUp { } } // TODO run exit finalizers (FFI) (this should happen in the FFI context beforeDestroy) + + // force sub-context threads to stop + for (Thread thread : new ArrayList<>(RContext.getInstance().threads.values())) { + thread.interrupt(); + try { + thread.join(10); + } catch (InterruptedException e) { + // nothing to be done + } + } throw new ExitException(status, false); } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/EvalThread.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/EvalThread.java index cfa1fe7b79..1f7f44cfd9 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/EvalThread.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/EvalThread.java @@ -53,7 +53,7 @@ public class EvalThread extends Thread { private RList evalResult; private Semaphore init = new Semaphore(0); - public static final Map<Integer, Thread> threads = new ConcurrentHashMap<>(); + private final Map<Integer, Thread> threadMap; /** This table is required to create several bunches of child contexts. */ public static final Map<Integer, Integer> idToMultiSlotTable = new ConcurrentHashMap<>(); @@ -61,11 +61,12 @@ public class EvalThread extends Thread { /** We use a separate counter for threads since ConcurrentHashMap.size() is not reliable. */ public static final AtomicInteger threadCnt = new AtomicInteger(0); - public EvalThread(ChildContextInfo info, Source source, boolean usePolyglot) { + public EvalThread(Map<Integer, Thread> threadMap, ChildContextInfo info, Source source, boolean usePolyglot) { + this.threadMap = threadMap; this.info = info; this.source = source; threadCnt.incrementAndGet(); - threads.put(info.getId(), this); + threadMap.put(info.getId(), this); idToMultiSlotTable.put(info.getId(), info.getMultiSlotInd()); this.usePolyglot = usePolyglot; this.truffleContext = usePolyglot ? null : info.createTruffleContext(); @@ -82,7 +83,7 @@ public class EvalThread extends Thread { evalResult = run(truffleContext, info, source); } } finally { - threads.remove(info.getId()); + threadMap.remove(info.getId()); threadCnt.decrementAndGet(); } } @@ -109,8 +110,9 @@ public class EvalThread extends Thread { parent = truffleContext.enter(); // this is the engine for the new child context Engine rEngine = RContext.getEngine(); + // Object eval = rEngine.eval(rEngine.parse(source), rEngine.getGlobalFrame()); Object evalResult = rEngine.parseAndEval(source, rEngine.getGlobalFrame(), false); - result = createEvalResult(evalResult, false); + result = createEvalResult(evalResult == null ? RNull.instance : evalResult, false); } catch (ParseException e) { e.report(info.getStdout()); result = createErrorResult(e.getMessage()); diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java index 30f785da5a..e229eb4c45 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java @@ -46,6 +46,7 @@ import java.util.List; import java.util.Map; import java.util.TimeZone; import java.util.WeakHashMap; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Executor; import java.util.function.Supplier; @@ -353,6 +354,7 @@ public final class RContext implements RTruffleObject { public final WeakHashMap<Source, REnvironment> sourceRefEnvironments = new WeakHashMap<>(); public final WeakHashMap<Path, REnvironment> srcfileEnvironments = new WeakHashMap<>(); public final List<String> libraryPaths = new ArrayList<>(1); + public final Map<Integer, Thread> threads = new ConcurrentHashMap<>(); private final AllocationReporter allocationReporter; -- GitLab