diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/parallel/R/forkcluster_overrides.R b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/parallel/R/forkcluster_overrides.R index 7d1982fdcd0f71775e7bdc3d3ad3b4dcb956973a..7c90db9acccf402919ddfa99e467674380751619 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/parallel/R/forkcluster_overrides.R +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/parallel/R/forkcluster_overrides.R @@ -14,6 +14,8 @@ # ## Derived from snow and parallel packages +## Note: the same code is used in snow_overrides.R, reflect any updates in that file +## TODO: get rid of this redundancy eval(expression({ diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/snow/R/snow_overrides.R b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/snow/R/snow_overrides.R index 77eaaffcacf4bcc6b9cf37330adbab7d63777885..5bc2b2133e14357b720bd031079f7a1c1e57f96c 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/snow/R/snow_overrides.R +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/snow/R/snow_overrides.R @@ -14,6 +14,8 @@ # ## Derived from snow and parallel packages +## Note: the same code is used in forkcluster_overrides.R, reflect any updates in that file +## TODO: get rid of this redundancy eval(expression({ diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/Utils.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/Utils.java index 63ba73313ce8ed15c637cf8448a05f1223025d2c..4cabec6d9846a2ba15360f106c34d5a12bba6d83 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/Utils.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/Utils.java @@ -30,6 +30,7 @@ import java.io.InputStreamReader; import java.nio.file.FileSystem; import java.nio.file.FileSystems; import java.nio.file.Path; +import java.nio.file.Paths; import java.nio.file.attribute.FileTime; import java.nio.file.attribute.PosixFilePermission; import java.util.Set; @@ -249,27 +250,37 @@ public final class Utils { * of the dirs is writable null is returned. */ public static Path getLogPath(String fileNamePrefix) { - String dir = RContext.isEmbedded() ? System.getProperty("java.io.tmpdir") : System.getProperty("user.dir"); + String tmpDir = robustGetProperty("java.io.tmpdir"); + String dir = RContext.isEmbedded() ? tmpDir : robustGetProperty("user.dir"); int dirId = 0; + if (dir != null && tmpDir != null && Paths.get(dir).startsWith(tmpDir) && dir.contains("R.INSTALL")) { + // Simple heuristic to find out if we are in the middle of package installation, in + // which case we do not want to write to the working directory, since the installation + // process will remove that directory when finished. + dirId = 1; + dir = robustGetProperty("user.home"); + } int pid = RContext.getInitialPid(); // Do not use PID if it was not set yet (logging/error during initialization) String pidStr = pid == 0 ? "" : "_pid" + Integer.toString(pid); String baseName = fileNamePrefix + pidStr + ".log"; while (true) { - Path path = FileSystems.getDefault().getPath(dir, baseName); - if (Files.isWritable(path.getParent()) && (!Files.exists(path) || Files.isWritable(path))) { - return path; + if (dir != null) { + Path path = FileSystems.getDefault().getPath(dir, baseName); + if (robustCheckWriteable(path)) { + return path; + } } switch (dirId) { case 0: if (RContext.isEmbedded()) { return null; } else { - dir = System.getProperty("user.home"); + dir = robustGetProperty("user.home"); } break; case 1: - dir = System.getProperty("java.io.tmpdir"); + dir = tmpDir; break; case 2: dir = REnvVars.rHome(); @@ -281,6 +292,31 @@ public final class Utils { } } + private static String robustGetProperty(String name) { + try { + return System.getProperty(name); + } catch (Throwable ex) { + // System.getProperty may throw SecurityException, we catch all since we really need to + // be robust at this point + logGetLogPathError(ex.getMessage()); + return null; + } + } + + private static boolean robustCheckWriteable(Path logFile) { + try { + return Files.isWritable(logFile.getParent()) && (!Files.exists(logFile) || Files.isWritable(logFile)); + } catch (Throwable ex) { + // may throw SecurityException, we catch all since we really need to be robust + logGetLogPathError(ex.getMessage()); + return false; + } + } + + private static void logGetLogPathError(String message) { + System.err.println("Note: error during determining the error log file location: " + message); + } + /** * Performs "~" expansion and also checks whether we need to take special case over relative * paths due to the curwd having moved from the initial setting. In the latter case, if the path diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/NativeDataAccess.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/NativeDataAccess.java index e7211789f1975cd84b2787e81dcb28810c5a0b1f..00c6e8e74723b6e0ac90236044e1cff67b9a2b60 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/NativeDataAccess.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/NativeDataAccess.java @@ -212,8 +212,8 @@ public final class NativeDataAccess { // The counter is initialized to invalid address and incremented by 2 to always get invalid // address value private static final AtomicLong counter = new AtomicLong(0xdef000000000001L); - private static final ConcurrentHashMap<Long, WeakReference<RObject>> nativeMirrors = new ConcurrentHashMap<>(); - private static final ConcurrentHashMap<Long, RuntimeException> nativeMirrorInfo = new ConcurrentHashMap<>(); + private static final ConcurrentHashMap<Long, WeakReference<RObject>> nativeMirrors = new ConcurrentHashMap<>(512); + private static final ConcurrentHashMap<Long, RuntimeException> nativeMirrorInfo = TRACE_MIRROR_ALLOCATION_SITES ? new ConcurrentHashMap<>() : null; public static CallTarget createIsPointer() { return Truffle.getRuntime().createCallTarget(new InteropRootNode() { @@ -309,7 +309,7 @@ public final class NativeDataAccess { } private static RuntimeException reportDataAccessError(long address) { - RuntimeException location = nativeMirrorInfo.get(address); + RuntimeException location = TRACE_MIRROR_ALLOCATION_SITES ? nativeMirrorInfo.get(address) : null; if (location != null) { System.out.println("Location at which the native mirror was allocated:"); location.printStackTrace(); diff --git a/com.oracle.truffle.r.test.packages/r/install.packages.R b/com.oracle.truffle.r.test.packages/r/install.packages.R index 5c44bbe384b82c442ea3b736b7b594bd8b03d285..5492e58a08775ca4ee6baba77045c980c6c1cdb7 100644 --- a/com.oracle.truffle.r.test.packages/r/install.packages.R +++ b/com.oracle.truffle.r.test.packages/r/install.packages.R @@ -318,10 +318,15 @@ set.repos <- function() { # set the FastR internal repo repos[["FASTR"]] <- paste0("file://", normalizePath("com.oracle.truffle.r.test.native/packages/repo")) } else if (name == "SNAPSHOT") { - con <- file("etc/DEFAULT_CRAN_MIRROR", "r"); tryCatch({ + con <- file("etc/DEFAULT_CRAN_MIRROR", "r"); cran.mirror <<- readLines(con)[[1]] - }, finally=function() close(con)) + close(con) + }, error = function(err) { + cat("ERROR while getting etc/DEFAULT_CRAN_MIRROR, are you running this in FastR home directory?") + print(err) + exit(1) + }) repos[["CRAN"]] <- cran.mirror } else { # User defined diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/utils/TestHelp.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/utils/TestHelp.java index a026d7ee85ea97a5c7430bc4de6dacd4bb043c13..a165fa56829d7b2076a8c41314ff1b69ed358d7f 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/utils/TestHelp.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/utils/TestHelp.java @@ -22,8 +22,9 @@ */ package com.oracle.truffle.r.test.library.utils; -import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertThat; +import org.hamcrest.CoreMatchers; import org.junit.Test; import com.oracle.truffle.r.runtime.context.RContext.ContextKind; @@ -47,10 +48,10 @@ public class TestHelp extends TestBase { private static void assertHelpResult(String result, String startsWith, String... contains) { if (startsWith != null) { - assertTrue(result.startsWith(startsWith)); + assertThat(result, CoreMatchers.startsWith(startsWith)); } for (String s : contains) { - assertTrue(result.contains(s)); + assertThat(result, CoreMatchers.containsString(s)); } } }