changeset 50449:84d0fe3cefd4

8202105: Console echo is disabled when exiting jshell Summary: Preserving original terminal echo state when Console.readPassword finishes. Reviewed-by: sherman, martin
author jlahoda
date Mon, 30 Apr 2018 15:03:08 +0200
parents 764aea6237ad
children 3deb300f0e55
files src/java.base/share/classes/java/io/Console.java src/java.base/unix/native/libjava/Console_md.c src/java.base/windows/native/libjava/Console_md.c
diffstat 3 files changed, 31 insertions(+), 55 deletions(-) [+]
line wrap: on
line diff
--- a/src/java.base/share/classes/java/io/Console.java	Mon Apr 30 12:19:55 2018 +0200
+++ b/src/java.base/share/classes/java/io/Console.java	Mon Apr 30 15:03:08 2018 +0200
@@ -311,9 +311,9 @@
         char[] passwd = null;
         synchronized (writeLock) {
             synchronized(readLock) {
-                boolean echoWasOn;
+                installShutdownHook();
                 try {
-                    echoWasOn = echo(false);
+                    restoreEcho = echo(false);
                 } catch (IOException x) {
                     throw new IOError(x);
                 }
@@ -326,7 +326,8 @@
                     ioe = new IOError(x);
                 } finally {
                     try {
-                        echo(echoWasOn);
+                        if (restoreEcho)
+                            restoreEcho = echo(true);
                     } catch (IOException x) {
                         if (ioe == null)
                             ioe = new IOError(x);
@@ -342,6 +343,31 @@
         return passwd;
     }
 
+    private void installShutdownHook() {
+        if (shutdownHookInstalled)
+            return;
+        try {
+            // Add a shutdown hook to restore console's echo state should
+            // it be necessary.
+            SharedSecrets.getJavaLangAccess()
+                .registerShutdownHook(0 /* shutdown hook invocation order */,
+                    false /* only register if shutdown is not in progress */,
+                    new Runnable() {
+                        public void run() {
+                            try {
+                                if (restoreEcho) {
+                                    echo(true);
+                                }
+                            } catch (IOException x) { }
+                        }
+                    });
+        } catch (IllegalStateException e) {
+            // shutdown is already in progress and readPassword is first used
+            // by a shutdown hook
+        }
+        shutdownHookInstalled = true;
+    }
+
    /**
     * Reads a password or passphrase from the console with echoing disabled
     *
@@ -372,6 +398,8 @@
     private Formatter formatter;
     private Charset cs;
     private char[] rcb;
+    private boolean restoreEcho;
+    private boolean shutdownHookInstalled;
     private static native String encoding();
     /*
      * Sets the console echo status to {@code on} and returns the previous
@@ -381,12 +409,6 @@
      * @return true if the previous console echo status is on
      */
     private static native boolean echo(boolean on) throws IOException;
-    /*
-     * Returns the current console echo on/off status.
-     * @return true if the cosole echo is on
-     */
-    private static native boolean echo0() throws IOException;
-    private static boolean echoOn;
 
     private char[] readline(boolean zeroOut) throws IOException {
         int len = reader.read(rcb, 0, rcb.length);
@@ -531,25 +553,6 @@
 
     // Set up JavaIOAccess in SharedSecrets
     static {
-        try {
-            // Add a shutdown hook to restore console's echo state should
-            // it be necessary.
-            SharedSecrets.getJavaLangAccess()
-                .registerShutdownHook(0 /* shutdown hook invocation order */,
-                    false /* only register if shutdown is not in progress */,
-                    new Runnable() {
-                        public void run() {
-                            try {
-                                if (cons != null)
-                                    echo(echoOn);
-                            } catch (IOException x) { }
-                        }
-                    });
-        } catch (IllegalStateException e) {
-            // shutdown is already in progress and console is first used
-            // by a shutdown hook
-        }
-
         SharedSecrets.setJavaIOAccess(new JavaIOAccess() {
             public Console console() {
                 if (istty()) {
@@ -591,10 +594,5 @@
                      readLock,
                      cs));
         rcb = new char[1024];
-        try {
-            echoOn = echo0();
-        } catch (IOException x) {
-            echoOn = true;
-        }
     }
 }
--- a/src/java.base/unix/native/libjava/Console_md.c	Mon Apr 30 12:19:55 2018 +0200
+++ b/src/java.base/unix/native/libjava/Console_md.c	Mon Apr 30 15:03:08 2018 +0200
@@ -67,14 +67,3 @@
     }
     return old;
 }
-
-JNIEXPORT jboolean JNICALL
-Java_java_io_Console_echo0(JNIEnv *env, jclass cls) {
-    struct termios tio;
-    int tty = fileno(stdin);
-    if (tcgetattr(tty, &tio) == -1) {
-        JNU_ThrowIOExceptionWithLastError(env, "tcgetattr failed");
-        return JNI_TRUE;
-    }
-    return (tio.c_lflag & ECHO) != 0;
-}
--- a/src/java.base/windows/native/libjava/Console_md.c	Mon Apr 30 12:19:55 2018 +0200
+++ b/src/java.base/windows/native/libjava/Console_md.c	Mon Apr 30 15:03:08 2018 +0200
@@ -82,14 +82,3 @@
     }
     return old;
 }
-
-JNIEXPORT jboolean JNICALL
-Java_java_io_Console_echo0(JNIEnv *env, jclass cls)
-{
-    DWORD fdwMode;
-    if (! GetConsoleMode(hStdIn, &fdwMode)) {
-        JNU_ThrowIOExceptionWithLastError(env, "GetConsoleMode failed");
-        return JNI_TRUE;
-    }
-    return (fdwMode & ENABLE_ECHO_INPUT) != 0;
-}