8202105: Console echo is disabled when exiting jshell

Preserving original terminal echo state when Console.readPassword finishes.

Reviewed-by: sherman, martin
This commit is contained in:
Jan Lahoda 2018-04-30 15:03:08 +02:00
parent b9490e5760
commit f7afa8ff53
3 changed files with 31 additions and 55 deletions

View file

@ -311,9 +311,9 @@ public final class Console implements Flushable
char[] passwd = null; char[] passwd = null;
synchronized (writeLock) { synchronized (writeLock) {
synchronized(readLock) { synchronized(readLock) {
boolean echoWasOn; installShutdownHook();
try { try {
echoWasOn = echo(false); restoreEcho = echo(false);
} catch (IOException x) { } catch (IOException x) {
throw new IOError(x); throw new IOError(x);
} }
@ -326,7 +326,8 @@ public final class Console implements Flushable
ioe = new IOError(x); ioe = new IOError(x);
} finally { } finally {
try { try {
echo(echoWasOn); if (restoreEcho)
restoreEcho = echo(true);
} catch (IOException x) { } catch (IOException x) {
if (ioe == null) if (ioe == null)
ioe = new IOError(x); ioe = new IOError(x);
@ -342,6 +343,31 @@ public final class Console implements Flushable
return passwd; 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 * Reads a password or passphrase from the console with echoing disabled
* *
@ -372,6 +398,8 @@ public final class Console implements Flushable
private Formatter formatter; private Formatter formatter;
private Charset cs; private Charset cs;
private char[] rcb; private char[] rcb;
private boolean restoreEcho;
private boolean shutdownHookInstalled;
private static native String encoding(); private static native String encoding();
/* /*
* Sets the console echo status to {@code on} and returns the previous * Sets the console echo status to {@code on} and returns the previous
@ -381,12 +409,6 @@ public final class Console implements Flushable
* @return true if the previous console echo status is on * @return true if the previous console echo status is on
*/ */
private static native boolean echo(boolean on) throws IOException; 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 { private char[] readline(boolean zeroOut) throws IOException {
int len = reader.read(rcb, 0, rcb.length); int len = reader.read(rcb, 0, rcb.length);
@ -531,25 +553,6 @@ public final class Console implements Flushable
// Set up JavaIOAccess in SharedSecrets // Set up JavaIOAccess in SharedSecrets
static { 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() { SharedSecrets.setJavaIOAccess(new JavaIOAccess() {
public Console console() { public Console console() {
if (istty()) { if (istty()) {
@ -591,10 +594,5 @@ public final class Console implements Flushable
readLock, readLock,
cs)); cs));
rcb = new char[1024]; rcb = new char[1024];
try {
echoOn = echo0();
} catch (IOException x) {
echoOn = true;
}
} }
} }

View file

@ -67,14 +67,3 @@ Java_java_io_Console_echo(JNIEnv *env,
} }
return old; 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;
}

View file

@ -82,14 +82,3 @@ Java_java_io_Console_echo(JNIEnv *env, jclass cls, jboolean on)
} }
return old; 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;
}