From ff307d5d27ff622b52c1f948b725b89554480b7a Mon Sep 17 00:00:00 2001 From: Mick Jordan <mick.jordan@oracle.com> Date: Mon, 20 Jun 2016 09:02:42 -0700 Subject: [PATCH] In embedded mode delay JLine console creation until necessary; remove ConsoleHandler.getWidth --- .../engine/shell/EmbeddedConsoleHandler.java | 62 ++++++++++++------- .../r/engine/shell/JLineConsoleHandler.java | 20 +++--- .../truffle/r/engine/shell/RCommand.java | 35 ++++------- .../truffle/r/nodes/builtin/base/Format.java | 2 +- .../oracle/truffle/r/runtime/ROptions.java | 2 +- .../r/runtime/context/ConsoleHandler.java | 6 -- .../context/DefaultConsoleHandler.java | 5 -- 7 files changed, 66 insertions(+), 66 deletions(-) diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/EmbeddedConsoleHandler.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/EmbeddedConsoleHandler.java index ac19422484..0e5040ee58 100644 --- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/EmbeddedConsoleHandler.java +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/EmbeddedConsoleHandler.java @@ -23,7 +23,9 @@ package com.oracle.truffle.r.engine.shell; import com.oracle.truffle.r.runtime.RInterfaceCallbacks; +import com.oracle.truffle.r.runtime.RStartParams; import com.oracle.truffle.r.runtime.context.ConsoleHandler; +import com.oracle.truffle.r.runtime.context.DefaultConsoleHandler; import com.oracle.truffle.r.runtime.ffi.REmbedRFFI; import com.oracle.truffle.r.runtime.ffi.RFFIFactory; @@ -31,26 +33,42 @@ import com.oracle.truffle.r.runtime.ffi.RFFIFactory; * In embedded mode the console functions as defined in {@code Rinterface.h} can be overridden. This * class supports that, delegating to a standard console handler if not redirected. * + * N.B. At the time the constructor is created, we do not know if the console is overridden so we + * have be lazy about that. + * */ public class EmbeddedConsoleHandler implements ConsoleHandler { + private final RStartParams startParams; + /** + * Only not {@code null} when console is not overridden. + */ private ConsoleHandler delegate; private REmbedRFFI rEmbedRFFI; + private String prompt; - EmbeddedConsoleHandler(ConsoleHandler delegate) { - this.delegate = delegate; + EmbeddedConsoleHandler(RStartParams startParams) { + this.startParams = startParams; } private REmbedRFFI getREmbedRFFI() { if (rEmbedRFFI == null) { rEmbedRFFI = RFFIFactory.getRFFI().getREmbedRFFI(); + if (!(RInterfaceCallbacks.R_WriteConsole.isOverridden() || RInterfaceCallbacks.R_ReadConsole.isOverridden())) { + if (startParams.getNoReadline()) { + delegate = new DefaultConsoleHandler(System.in, System.out); + } else { + delegate = new JLineConsoleHandler(startParams); + } + } } return rEmbedRFFI; } @Override public void println(String s) { - if (RInterfaceCallbacks.R_WriteConsole.isOverridden()) { + getREmbedRFFI(); + if (delegate == null) { getREmbedRFFI().writeConsole(s); getREmbedRFFI().writeConsole("\n"); } else { @@ -61,8 +79,9 @@ public class EmbeddedConsoleHandler implements ConsoleHandler { @Override public void print(String s) { - if (RInterfaceCallbacks.R_WriteConsole.isOverridden()) { - getREmbedRFFI().writeConsole(s); + getREmbedRFFI(); + if (delegate == null) { + rEmbedRFFI.writeConsole(s); } else { delegate.print(s); } @@ -71,9 +90,10 @@ public class EmbeddedConsoleHandler implements ConsoleHandler { @Override public void printErrorln(String s) { - if (RInterfaceCallbacks.R_WriteConsole.isOverridden()) { - getREmbedRFFI().writeErrConsole(s); - getREmbedRFFI().writeErrConsole("\n"); + getREmbedRFFI(); + if (delegate == null) { + rEmbedRFFI.writeErrConsole(s); + rEmbedRFFI.writeErrConsole("\n"); } else { delegate.printErrorln(s); } @@ -82,8 +102,9 @@ public class EmbeddedConsoleHandler implements ConsoleHandler { @Override public void printError(String s) { - if (RInterfaceCallbacks.R_WriteConsole.isOverridden()) { - getREmbedRFFI().writeErrConsole(s); + getREmbedRFFI(); + if (delegate == null) { + rEmbedRFFI.writeErrConsole(s); } else { delegate.printError(s); } @@ -92,8 +113,9 @@ public class EmbeddedConsoleHandler implements ConsoleHandler { @Override public String readLine() { - if (RInterfaceCallbacks.R_ReadConsole.isOverridden()) { - return getREmbedRFFI().readConsole(delegate.getPrompt()); + getREmbedRFFI(); + if (delegate == null) { + return rEmbedRFFI.readConsole(prompt); } else { return delegate.readLine(); } @@ -101,28 +123,26 @@ public class EmbeddedConsoleHandler implements ConsoleHandler { @Override public boolean isInteractive() { - return delegate.isInteractive(); + return startParams.getInteractive(); } @Override public String getPrompt() { - return delegate.getPrompt(); + return prompt; } @Override public void setPrompt(String prompt) { - delegate.setPrompt(prompt); - - } + this.prompt = prompt; + if (delegate != null) { + delegate.setPrompt(prompt); + } - @Override - public int getWidth() { - return delegate.getWidth(); } @Override public String getInputDescription() { - return delegate.getInputDescription(); + return "<embedded input>"; } } diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/JLineConsoleHandler.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/JLineConsoleHandler.java index 3dca9591b0..1f78b479c4 100644 --- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/JLineConsoleHandler.java +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/JLineConsoleHandler.java @@ -28,9 +28,9 @@ import java.io.PrintWriter; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.r.runtime.RInternalSourceDescriptions; +import com.oracle.truffle.r.runtime.RStartParams; import com.oracle.truffle.r.runtime.Utils; import com.oracle.truffle.r.runtime.context.ConsoleHandler; -import com.oracle.truffle.r.runtime.context.RContext; import jline.console.ConsoleReader; import jline.console.UserInterruptException; @@ -42,10 +42,17 @@ class JLineConsoleHandler implements ConsoleHandler { private final boolean isInteractive; private final PrintWriter printWriter; - JLineConsoleHandler(boolean isInteractive, ConsoleReader console) { - this.console = console; + JLineConsoleHandler(RStartParams startParams) { + try { + console = new ConsoleReader(System.in, System.out); + console.setHandleUserInterrupt(true); + console.setExpandEvents(false); + } catch (IOException ex) { + throw Utils.fail("unexpected error opening console reader"); + } + // long start = System.currentTimeMillis(); printWriter = new PrintWriter(console.getOutput()); - this.isInteractive = isInteractive; + this.isInteractive = startParams.getInteractive(); } @Override @@ -108,11 +115,6 @@ class JLineConsoleHandler implements ConsoleHandler { console.setPrompt(prompt); } - @Override - public int getWidth() { - return RContext.CONSOLE_WIDTH; - } - @Override public String getInputDescription() { return RInternalSourceDescriptions.SHELL_INPUT; diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RCommand.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RCommand.java index c0e4ab7be4..ee7e0b1aed 100644 --- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RCommand.java +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RCommand.java @@ -29,8 +29,6 @@ import java.io.Console; import java.io.EOFException; import java.io.File; import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; import java.nio.file.Files; import java.util.List; @@ -58,7 +56,6 @@ import com.oracle.truffle.r.runtime.context.RContext.ContextKind; import com.oracle.truffle.r.runtime.data.RLogicalVector; import com.oracle.truffle.r.runtime.data.RStringVector; -import jline.console.ConsoleReader; import jline.console.UserInterruptException; /** @@ -119,8 +116,6 @@ public class RCommand { * checked. */ ConsoleHandler consoleHandler; - InputStream consoleInput = System.in; - OutputStream consoleOutput = System.out; if (fileArg != null) { List<String> lines; String filePath; @@ -148,31 +143,25 @@ public class RCommand { * GnuR behavior differs from the manual entry for {@code interactive} in that {@code * --interactive} never applies to {@code -e/-f}, only to console input that has been * redirected from a pipe/file etc. + * + * If we are in embedded mode, the creation of ConsoleReader and the ConsoleHandler + * should be lazy, as these may not be necessary and can cause hangs if stdin has been + * redirected. */ Console sysConsole = System.console(); - boolean useReadLine = !rsp.getNoReadline(); - ConsoleReader consoleReader = null; - if (useReadLine) { - try { - consoleReader = new ConsoleReader(consoleInput, consoleOutput); - consoleReader.setHandleUserInterrupt(true); - consoleReader.setExpandEvents(false); - } catch (IOException ex) { - throw Utils.fail("unexpected error opening console reader"); - } - } boolean isInteractive = options.getBoolean(INTERACTIVE) || sysConsole != null; if (!isInteractive && rsp.getSaveAction() != SA_TYPE.SAVE && rsp.getSaveAction() != SA_TYPE.NOSAVE) { throw Utils.rSuicide("you must specify '--save', '--no-save' or '--vanilla'"); } - // long start = System.currentTimeMillis(); - if (useReadLine) { - consoleHandler = new JLineConsoleHandler(isInteractive, consoleReader); - } else { - consoleHandler = new DefaultConsoleHandler(consoleInput, consoleOutput); - } if (embedded) { - consoleHandler = new EmbeddedConsoleHandler(consoleHandler); + consoleHandler = new EmbeddedConsoleHandler(rsp); + } else { + boolean useReadLine = !rsp.getNoReadline(); + if (useReadLine) { + consoleHandler = new JLineConsoleHandler(rsp); + } else { + consoleHandler = new DefaultConsoleHandler(System.in, System.out); + } } } return ContextInfo.create(rsp, ContextKind.SHARE_NOTHING, null, consoleHandler).apply(PolyglotEngine.newBuilder()).build(); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Format.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Format.java index 341d931b55..b109af35f2 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Format.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Format.java @@ -57,7 +57,7 @@ public abstract class Format extends RBuiltinNode { if (printConfig == null) { printConfig = new Config(); } - printConfig.width = RContext.getInstance().getConsoleHandler().getWidth(); + printConfig.width = (int) RContext.getInstance().stateROptions.getValue("width"); printConfig.naWidth = RRuntime.STRING_NA.length(); printConfig.naWidthNoQuote = RRuntime.NA_HEADER.length(); printConfig.digits = 7 /* default */; diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ROptions.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ROptions.java index 7d2ed0909a..a2a7f8b73f 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ROptions.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ROptions.java @@ -130,7 +130,7 @@ public class ROptions { map.put("verbose", RDataFactory.createLogicalVectorFromScalar(startParams.getVerbose())); map.put("nwarnings", RDataFactory.createIntVectorFromScalar(50)); map.put("warning.length", RDataFactory.createIntVectorFromScalar(1000)); - map.put("width", RDataFactory.createIntVectorFromScalar(80)); + map.put("width", RDataFactory.createIntVectorFromScalar(RContext.CONSOLE_WIDTH)); map.put("browserNLdisabled", RDataFactory.createLogicalVectorFromScalar(false)); boolean cBoundsCheck = optionFromEnvVar("R_C_BOUNDS_CHECK", envVars); map.put("CBoundsCheck", RDataFactory.createLogicalVectorFromScalar(cBoundsCheck)); diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/ConsoleHandler.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/ConsoleHandler.java index ab347547db..f238108b70 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/ConsoleHandler.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/ConsoleHandler.java @@ -95,12 +95,6 @@ public interface ConsoleHandler { @TruffleBoundary void setPrompt(String prompt); - /** - * Get the console width. - */ - @TruffleBoundary - int getWidth(); - String getInputDescription(); default void setHistoryFrom(@SuppressWarnings("unused") File file) { diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/DefaultConsoleHandler.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/DefaultConsoleHandler.java index e7cd144b26..18f2a36cce 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/DefaultConsoleHandler.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/DefaultConsoleHandler.java @@ -87,11 +87,6 @@ public class DefaultConsoleHandler implements ConsoleHandler { this.prompt = prompt; } - @Override - public int getWidth() { - return 80; - } - @Override public String getInputDescription() { return "<PolyglotEngine env input>"; -- GitLab