From 79ef398fd1ce23f55dfabe214d9e3d8cf2183105 Mon Sep 17 00:00:00 2001
From: Mick Jordan <mick.jordan@oracle.com>
Date: Sat, 25 Feb 2017 16:51:02 -0800
Subject: [PATCH] [GR-2982] Remove temporary directory on context exit; share
 parent tempdir for SHARED_PARENT_RW contexts.

---
 .../oracle/truffle/r/runtime/RCleanUp.java    |  3 +-
 .../truffle/r/runtime/TempPathName.java       | 44 ++++++++++++++++++-
 .../truffle/r/runtime/context/RContext.java   |  3 +-
 3 files changed, 46 insertions(+), 4 deletions(-)

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 3e303f3c0e..436e252e5d 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
@@ -104,8 +104,7 @@ public class RCleanUp {
                 RInternalError.reportError(t);
             }
         }
-        // TODO run exit finalizers (FFI)
-        // TODO clean tmpdir
+        // TODO run exit finalizers (FFI) (this should happen in the FFI context beforeDestroy)
         throw new ExitException(status);
 
     }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/TempPathName.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/TempPathName.java
index d0783f13cf..0975c771c1 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/TempPathName.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/TempPathName.java
@@ -23,8 +23,14 @@
 package com.oracle.truffle.r.runtime;
 
 import java.io.File;
+import java.io.IOException;
 import java.nio.file.FileSystems;
+import java.nio.file.FileVisitResult;
+import java.nio.file.Files;
 import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.attribute.BasicFileAttributes;
 import java.util.Random;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
@@ -47,6 +53,11 @@ public class TempPathName implements RContext.ContextState {
 
     @Override
     public RContext.ContextState initialize(RContext context) {
+        if (context.getKind() == RContext.ContextKind.SHARE_PARENT_RW) {
+            // share tempdir with parent
+            tempDirPath = context.getParent().stateTempPath.tempDirPath;
+            return this;
+        }
         final String[] envVars = new String[]{"TMPDIR", "TMP", "TEMP"};
         String startingTempDir = null;
         for (String envVar : envVars) {
@@ -72,13 +83,26 @@ public class TempPathName implements RContext.ContextState {
         return this;
     }
 
+    @Override
+    public void beforeDestroy(RContext context) {
+        if (context.getKind() == RContext.ContextKind.SHARE_PARENT_RW) {
+            return;
+        }
+        try {
+            Files.walkFileTree(Paths.get(tempDirPath), new DeleteVisitor());
+        } catch (Throwable e) {
+            // unexpected and we are exiting anyway
+        }
+    }
+
     private static boolean isWriteableDirectory(String path) {
         File f = new File(path);
         return f.exists() && f.isDirectory() && f.canWrite();
     }
 
     public static String tempDirPath() {
-        return RContext.getInstance().stateTempPath.tempDirPath;
+        String result = RContext.getInstance().stateTempPath.tempDirPath;
+        return result;
     }
 
     public static TempPathName newContextState() {
@@ -107,4 +131,22 @@ public class TempPathName implements RContext.ContextState {
             sb.append(RANDOM_CHARACTERS.charAt(rand.nextInt(RANDOM_CHARACTERS_LENGTH)));
         }
     }
+
+    private static final class DeleteVisitor extends SimpleFileVisitor<Path> {
+
+        @Override
+        public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
+            return del(file);
+        }
+
+        @Override
+        public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
+            return del(dir);
+        }
+
+        private static FileVisitResult del(Path p) throws IOException {
+            Files.delete(p);
+            return FileVisitResult.CONTINUE;
+        }
+    }
 }
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 36710352d1..7edb1892a2 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
@@ -424,7 +424,8 @@ public final class RContext extends ExecutionContext implements TruffleObject {
     public final WeakHashMap<Source, REnvironment> sourceRefEnvironments = new WeakHashMap<>();
 
     private ContextState[] contextStates() {
-        return new ContextState[]{stateREnvVars, stateRProfile, stateROptions, stateREnvironment, stateRErrorHandling, stateRConnection, stateStdConnections, stateRNG, stateRFFI, stateRSerialize,
+        return new ContextState[]{stateREnvVars, stateRProfile, stateTempPath, stateROptions, stateREnvironment, stateRErrorHandling, stateRConnection, stateStdConnections, stateRNG, stateRFFI,
+                        stateRSerialize,
                         stateLazyDBCache, stateInstrumentation, stateDLL};
     }
 
-- 
GitLab