Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

On Windows, JLine 3.4.0 interferes with the std input of sub process. #169

Closed
PhVdP opened this issue Sep 14, 2017 · 22 comments
Closed

On Windows, JLine 3.4.0 interferes with the std input of sub process. #169

PhVdP opened this issue Sep 14, 2017 · 22 comments

Comments

@PhVdP
Copy link

PhVdP commented Sep 14, 2017

Trying to use the JLine as library for a console launching OS or perl scripts, we found the following problem on Windows: Below the source code of small application, launching a subprocess from the input of JLine readline. When trying to execute a small perl script (see below), from the small application, the std input is blocked (see the image included). Calling this small application (from this small application) is also blocking. So, it is not a perl problem (;o).

Tests made on Windows 7 and Windows 2016 server.

import org.jline.reader.*; 
import org.jline.terminal.Terminal; 
import org.jline.terminal.TerminalBuilder; 
import java.util.concurrent.TimeUnit;

public class Main {

	public static void main(String[] args) {

		String prompt = "prompt> "; 
		String rightPrompt = null; 
		TerminalBuilder builder = null; 
		
		try {
			builder = TerminalBuilder.builder(); 

			Terminal terminal = builder
					.system(true)
					.build(); 

			LineReader reader = LineReaderBuilder.builder() 
					.terminal(terminal) 
					.build(); 
			
			while (true) { 

				String line = null; 
				try { 
					line = reader.readLine(prompt, rightPrompt, null, null); 
				} catch (UserInterruptException e) { 
					terminal.writer().println("User Interruption !");
				} catch (EndOfFileException e) { 
					return; 
				} 

				if (line == null) { 
					continue; 
				} 

				line = line.trim(); 

				terminal.writer().println("======>\"" + line + "\""); 

				terminal.flush(); 

				if (line.equalsIgnoreCase("quit") || line.equalsIgnoreCase("exit")) { 
					break; 
				} 

				runCommand (line);
			}
		}
		catch (Throwable t) {
			t.printStackTrace();
		}
	}

	public static int runCommand (String command) {

		int returnCode = -1;

		try {
			ProcessBuilder pb = new ProcessBuilder(command.split(" "));
			pb.inheritIO();
			Process p = pb.start ();  

			if (!p.waitFor(60,TimeUnit.SECONDS)) 
				System.out.println ("Timeout");
			else {
				returnCode = p.exitValue();
				System.out.println ("return code :" + returnCode);
			}

			return returnCode;

		} catch (Throwable t) { 
			t.printStackTrace();
			returnCode = -1;
		}
		return returnCode;
	}
}

Perl Script:

print  "Do you Wish To continue: Yes/No \n";
	my $contExec = <STDIN>;
	chomp($contExec);
	if ( uc($contExec) ne "YES" )
	{
        	print "Exiting\n";
		exit -1;
	}

image

@gnodet
Copy link
Member

gnodet commented Sep 14, 2017

Could you check if the following code works better ?

import org.jline.reader.*; 
import org.jline.terminal.Attributes; 
import org.jline.terminal.Terminal; 
import org.jline.terminal.TerminalBuilder; 
import java.util.concurrent.TimeUnit;

public class Main {

	public static void main(String[] args) {

		String prompt = "prompt> "; 
		String rightPrompt = null; 
		TerminalBuilder builder = null; 
		
		try {
			builder = TerminalBuilder.builder(); 

			Terminal terminal = builder
					.system(true)
					.build(); 

			LineReader reader = LineReaderBuilder.builder() 
					.terminal(terminal) 
					.build(); 
			
			while (true) { 

				String line = null; 
				try { 
					line = reader.readLine(prompt, rightPrompt, null, null); 
				} catch (UserInterruptException e) { 
					terminal.writer().println("User Interruption !");
				} catch (EndOfFileException e) { 
					return; 
				} 

				if (line == null) { 
					continue; 
				} 

				line = line.trim(); 

				terminal.writer().println("======>\"" + line + "\""); 

				terminal.flush(); 

				if (line.equalsIgnoreCase("quit") || line.equalsIgnoreCase("exit")) { 
					break; 
				} 

				Attributes attributes = terminal.getAttributes();
				runCommand (line);
				terminal.setAttributes(attributes);
			}
		}
		catch (Throwable t) {
			t.printStackTrace();
		}
	}

	public static int runCommand (String command) {

		int returnCode = -1;

		try {
			ProcessBuilder pb = new ProcessBuilder(command.split(" "));
			pb.inheritIO();
			Process p = pb.start ();  

			if (!p.waitFor(60,TimeUnit.SECONDS)) 
				System.out.println ("Timeout");
			else {
				returnCode = p.exitValue();
				System.out.println ("return code :" + returnCode);
			}

			return returnCode;

		} catch (Throwable t) { 
			t.printStackTrace();
			returnCode = -1;
		}
		return returnCode;
	}
}

@PhVdP
Copy link
Author

PhVdP commented Sep 14, 2017

So,

I've updated the imports:
import org.jline.reader.;
import org.jline.terminal.
;

and lines before calling the runCommand with:

                           terminal.writer().println("Save Attributes"); 
			terminal.flush(); 

			Attributes attributes = terminal.getAttributes();
			runCommand (line);
			terminal.setAttributes(attributes);

same problem:
capture1

@PhVdP
Copy link
Author

PhVdP commented Sep 14, 2017

Hi,

I made another test where the properties are saved just after creating the terminal:
Terminal terminal = builder
.system(true)
.build();

		terminal.writer().println("Save Attributes"); 
		terminal.flush(); 

		Attributes attribute1s = terminal.getAttributes();

and restoring those attributes before calling the runCommand

                            terminal.writer().println("Save Attributes & Restore initial"); 
			terminal.flush(); 

			Attributes attribute2s = terminal.getAttributes();
			terminal.setAttributes(attribute1s);
			runCommand (line);
			terminal.setAttributes(attribute2s);

same problem:
capture2

@gnodet
Copy link
Member

gnodet commented Sep 14, 2017

Yes, I misread the problem.
I think this is related to #140 et #141, where some jline terminal implementations will start a thread to consume input and process it.
As a work around, you may want to try closing the terminal before running the command and recreating it before reading a new line.
Maybe something more like

import org.jline.reader.*; 
import org.jline.terminal.Attributes; 
import org.jline.terminal.Terminal; 
import org.jline.terminal.TerminalBuilder; 
import java.util.concurrent.TimeUnit;

public class Main {

	public static void main(String[] args) {

		String prompt = "prompt> "; 
		String rightPrompt = null; 
		TerminalBuilder builder = null; 
		
		try {
			builder = TerminalBuilder.builder(); 

			while (true) { 

				String line = null; 

				try (Terminal terminal = builder
						.system(true)
						.build()) {

					LineReader reader = LineReaderBuilder.builder() 
							.terminal(terminal) 
							.build(); 
					try { 
						line = reader.readLine(prompt, rightPrompt, null, null); 
					} catch (UserInterruptException e) { 
						terminal.writer().println("User Interruption !");
					} catch (EndOfFileException e) { 
						return; 
					} 

					if (line == null) { 
						continue; 
					} 

					line = line.trim(); 

					terminal.writer().println("======>\"" + line + "\""); 
					terminal.flush(); 
				}

				if (line.equalsIgnoreCase("quit") || line.equalsIgnoreCase("exit")) { 
					break; 
				} 

				runCommand (line);
			}
		}
		catch (Throwable t) {
			t.printStackTrace();
		}
	}

	public static int runCommand (String command) {

		int returnCode = -1;

		try {
			ProcessBuilder pb = new ProcessBuilder(command.split(" "));
			pb.inheritIO();
			Process p = pb.start ();  

			if (!p.waitFor(60,TimeUnit.SECONDS)) 
				System.out.println ("Timeout");
			else {
				returnCode = p.exitValue();
				System.out.println ("return code :" + returnCode);
			}

			return returnCode;

		} catch (Throwable t) { 
			t.printStackTrace();
			returnCode = -1;
		}
		return returnCode;
	}
}

@PhVdP
Copy link
Author

PhVdP commented Sep 14, 2017

Hi,

Thanks for your help.

I guess you mean terminal.close() before runCommand() and then do a terminal builder.build () at each loop ?

See the code below and the result => same problem...

We loose also the history at each loop ? We made quite complex tab completion and quite long to initiate (using command grammar, etc...). So, this 'workaround' is not really suitable.

Perhaps this problem is linked with #140 (but not only because closing the terminal (i.e. the workaround) should work and it is not the case). My understanding is that the library is doing some initializations on the STDIN (for Windows) that changes the standard behavior and the sub process inherits those and be stuck (when typing a 'enter' key it goes to the begin of the line instead of accepting the new entry line).

Any other idea ?

import org.jline.reader.*;
import org.jline.terminal.*;
import java.util.concurrent.TimeUnit;
public class Main {
public static void main(String[] args) {
  String prompt = "prompt> ";
  String rightPrompt = null;
  TerminalBuilder builder = null;
  try {
    builder = TerminalBuilder.builder();
    while (true) {
       Terminal terminal = builder
        .system(true)
        .build();
       LineReader reader = LineReaderBuilder.builder()
        .terminal(terminal)
        .build();
        terminal.writer().println("Terminal & reader built");
        terminal.flush();
        String line = null;
        try {
          line = reader.readLine(prompt, rightPrompt, null, null);
        } catch (UserInterruptException e) {
         terminal.writer().println("User Interruption !");
       } catch (EndOfFileException e) {
        return;
       }
    if (line == null) {
      continue;
    }
    line = line.trim();
    terminal.writer().println("======>\"" + line + "\"");
    terminal.flush();

    if (line.equalsIgnoreCase("quit") || line.equalsIgnoreCase("exit")) { 
      break;
    }
    terminal.writer().println("Terminal to close before runing command");
    terminal.flush();
    terminal.close();

    runCommand (line);
    }
  }
  catch (Throwable t) {
    t.printStackTrace();
  }
}

public static int runCommand (String command) {

int returnCode = -1;
try {
ProcessBuilder pb = new ProcessBuilder(command.split(" "));
pb.inheritIO();
Process p = pb.start ();
if (!p.waitFor(60,TimeUnit.SECONDS))
  System.out.println ("Timeout");
  else {
  returnCode = p.exitValue();
  System.out.println ("return code :" + returnCode);
} 
  return returnCode;
  } catch (Throwable t) {
  t.printStackTrace();
  returnCode = -1;
  }
  return returnCode;
  }
}

image-2

after the timeout, back to the application and the new terminal creates is a dumb terminal...

image-4

@gnodet
Copy link
Member

gnodet commented Sep 14, 2017

Could you enable debug logging (using java.util.logging) and find out why the terminal can't be recreated ? It might give some useful information...

@PhVdP
Copy link
Author

PhVdP commented Sep 14, 2017

Voilà... Enabling the log in the first example... Indeed, some useful information (;o):

Sep 14, 2017 7:31:34 PM org.jline.utils.Log logr
FINE: Registering shutdown-hook: Thread[JLine Shutdown Hook,5,main]
Sep 14, 2017 7:31:34 PM org.jline.utils.Log logr
FINE: Adding shutdown-hook task: org.jline.terminal.impl.AbstractWindowsTerminal$$Lambda$11/104739310@44e81672
Sep 14, 2017 7:31:34 PM org.jline.utils.Log logr
FINE: Using terminal JnaWinSysTerminal
Sep 14, 2017 7:31:34 PM org.jline.utils.Log logr
FINEST: Registering signal INT with handler org.jline.terminal.impl.AbstractWindowsTerminal$$Lambda$159/2036958521@64616ca2
Sep 14, 2017 7:31:34 PM org.jline.utils.Log logr
FINEST: Registering signal WINCH with handler org.jline.terminal.impl.AbstractWindowsTerminal$$Lambda$159/2036958521@783e6358
Sep 14, 2017 7:31:34 PM org.jline.utils.Log logr
FINE: Error registering handler for signal WINCH
java.lang.reflect.InvocationTargetException
 at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
 at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
 at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
 at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
 at org.jline.utils.Signals.doRegister(Signals.java:94)
 at org.jline.utils.Signals.register(Signals.java:55)
 at org.jline.utils.Signals.register(Signals.java:35)
 at org.jline.terminal.impl.AbstractWindowsTerminal.handle(AbstractWindowsTerminal.java:105)
 at org.jline.reader.impl.LineReaderImpl.readLine(LineReaderImpl.java:475)
 at Main.main(Main.java:142)
Caused by: java.lang.IllegalArgumentException: Unknown signal: WINCH
 at sun.misc.Signal.<init>(Signal.java:143)
 ... 10 more

Sep 14, 2017 7:31:34 PM org.jline.utils.Log logr
FINEST: Registering signal CONT with handler org.jline.terminal.impl.AbstractWindowsTerminal$$Lambda$159/2036958521@1324409e
Sep 14, 2017 7:31:34 PM org.jline.utils.Log logr
FINE: Error registering handler for signal CONT
java.lang.reflect.InvocationTargetException
 at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
 at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
 at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
 at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
 at org.jline.utils.Signals.doRegister(Signals.java:94)
 at org.jline.utils.Signals.register(Signals.java:55)
 at org.jline.utils.Signals.register(Signals.java:35)
 at org.jline.terminal.impl.AbstractWindowsTerminal.handle(AbstractWindowsTerminal.java:105)
 at org.jline.reader.impl.LineReaderImpl.readLine(LineReaderImpl.java:476)
 at Main.main(Main.java:142)
Caused by: java.lang.IllegalArgumentException: Unknown signal: CONT
 at sun.misc.Signal.<init>(Signal.java:143)
 ... 10 more

Sep 14, 2017 7:31:34 PM org.jline.utils.Log logr
FINE: NonBlockingReader start
Sep 14, 2017 7:31:35 PM org.jline.utils.Log logr
FINEST: Binding: Reference[self-insert]
Sep 14, 2017 7:31:36 PM org.jline.utils.Log logr
FINEST: Binding: Reference[self-insert]
Sep 14, 2017 7:31:36 PM org.jline.utils.Log logr
FINEST: Binding: Reference[self-insert]
Sep 14, 2017 7:31:37 PM org.jline.utils.Log logr
FINEST: Binding: Reference[self-insert]
Sep 14, 2017 7:31:37 PM org.jline.utils.Log logr
FINEST: Binding: Reference[self-insert]
Sep 14, 2017 7:31:37 PM org.jline.utils.Log logr
FINEST: Binding: Reference[self-insert]
Sep 14, 2017 7:31:38 PM org.jline.utils.Log logr
FINEST: Binding: Reference[self-insert]
Sep 14, 2017 7:31:38 PM org.jline.utils.Log logr
FINEST: Binding: Reference[self-insert]
Sep 14, 2017 7:31:39 PM org.jline.utils.Log logr
FINEST: Binding: Reference[self-insert]
Sep 14, 2017 7:31:42 PM org.jline.utils.Log logr
FINEST: Binding: Reference[self-insert]
Sep 14, 2017 7:31:42 PM org.jline.utils.Log logr
FINEST: Binding: Reference[self-insert]
Sep 14, 2017 7:31:43 PM org.jline.utils.Log logr
FINEST: Binding: Reference[self-insert]
Sep 14, 2017 7:31:43 PM org.jline.utils.Log logr
FINEST: Binding: Reference[self-insert]
Sep 14, 2017 7:31:44 PM org.jline.utils.Log logr
FINEST: Binding: Reference[self-insert]
Sep 14, 2017 7:31:44 PM org.jline.utils.Log logr
FINEST: Binding: Reference[self-insert]
Sep 14, 2017 7:31:45 PM org.jline.utils.Log logr
FINEST: Binding: Reference[self-insert]
Sep 14, 2017 7:31:45 PM org.jline.utils.Log logr
FINEST: Binding: Reference[self-insert]
Sep 14, 2017 7:31:45 PM org.jline.utils.Log logr
FINEST: Binding: Reference[accept-line]
Sep 14, 2017 7:31:45 PM org.jline.utils.Log logr
FINEST: Registering signal INT with handler SIG_DFL
Sep 14, 2017 7:31:45 PM org.jline.utils.Log logr
FINEST: Registering signal WINCH with handler SIG_DFL
Sep 14, 2017 7:31:45 PM org.jline.utils.Log logr
FINE: Error registering default handler for signal WINCH
java.lang.reflect.InvocationTargetException
 at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
 at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
 at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
 at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
 at org.jline.utils.Signals.doRegister(Signals.java:94)
 at org.jline.utils.Signals.registerDefault(Signals.java:66)
 at org.jline.terminal.impl.AbstractWindowsTerminal.handle(AbstractWindowsTerminal.java:103)
 at org.jline.reader.impl.LineReaderImpl.readLine(LineReaderImpl.java:594)
 at Main.main(Main.java:142)
Caused by: java.lang.IllegalArgumentException: Unknown signal: WINCH
 at sun.misc.Signal.<init>(Signal.java:143)
 ... 9 more

Sep 14, 2017 7:31:45 PM org.jline.utils.Log logr
FINEST: Registering signal CONT with handler SIG_DFL
Sep 14, 2017 7:31:45 PM org.jline.utils.Log logr
FINE: Error registering default handler for signal CONT
java.lang.reflect.InvocationTargetException
 at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
 at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
 at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
 at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
 at org.jline.utils.Signals.doRegister(Signals.java:94)
 at org.jline.utils.Signals.registerDefault(Signals.java:66)
 at org.jline.terminal.impl.AbstractWindowsTerminal.handle(AbstractWindowsTerminal.java:103)
 at org.jline.reader.impl.LineReaderImpl.readLine(LineReaderImpl.java:597)
 at Main.main(Main.java:142)
Caused by: java.lang.IllegalArgumentException: Unknown signal: CONT
 at sun.misc.Signal.<init>(Signal.java:143)
 ... 9 more

@gnodet
Copy link
Member

gnodet commented Sep 15, 2017

Is that the full log ? I'm looking for the Unable to create a system terminal exception...

@PhVdP
Copy link
Author

PhVdP commented Sep 15, 2017

OK. Recreate the previous case:

  • Call terminal.close() before calling the run command
  • re-build the terminal and LineReader at the begin of each loop.
Sep 15, 2017 10:57:42 AM org.jline.utils.Log logr
FINE: Registering shutdown-hook: Thread[JLine Shutdown Hook,5,main]
Sep 15, 2017 10:57:42 AM org.jline.utils.Log logr
FINE: Adding shutdown-hook task: org.jline.terminal.impl.AbstractWindowsTerminal$$Lambda$11/874088044@4fccd51b
Sep 15, 2017 10:57:42 AM org.jline.utils.Log logr
FINE: Using terminal JnaWinSysTerminal
Sep 15, 2017 10:57:42 AM org.jline.utils.Log logr
FINEST: Registering signal INT with handler org.jline.terminal.impl.AbstractWindowsTerminal$$Lambda$159/1798286609@3b81a1bc
Sep 15, 2017 10:57:42 AM org.jline.utils.Log logr
FINEST: Registering signal WINCH with handler org.jline.terminal.impl.AbstractWindowsTerminal$$Lambda$159/1798286609@4e04a765
Sep 15, 2017 10:57:42 AM org.jline.utils.Log logr
FINE: Error registering handler for signal WINCH
java.lang.reflect.InvocationTargetException
 at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
 at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
 at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
 at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
 at org.jline.utils.Signals.doRegister(Signals.java:94)
 at org.jline.utils.Signals.register(Signals.java:55)
 at org.jline.utils.Signals.register(Signals.java:35)
 at org.jline.terminal.impl.AbstractWindowsTerminal.handle(AbstractWindowsTerminal.java:105)
 at org.jline.reader.impl.LineReaderImpl.readLine(LineReaderImpl.java:475)
 at Main.main(Main.java:142)
Caused by: java.lang.IllegalArgumentException: Unknown signal: WINCH
 at sun.misc.Signal.<init>(Signal.java:143)
 ... 10 more

Sep 15, 2017 10:57:42 AM org.jline.utils.Log logr
FINEST: Registering signal CONT with handler org.jline.terminal.impl.AbstractWindowsTerminal$$Lambda$159/1798286609@180bc464
Sep 15, 2017 10:57:42 AM org.jline.utils.Log logr
FINE: Error registering handler for signal CONT
java.lang.reflect.InvocationTargetException
 at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
 at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
 at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
 at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
 at org.jline.utils.Signals.doRegister(Signals.java:94)
 at org.jline.utils.Signals.register(Signals.java:55)
 at org.jline.utils.Signals.register(Signals.java:35)
 at org.jline.terminal.impl.AbstractWindowsTerminal.handle(AbstractWindowsTerminal.java:105)
 at org.jline.reader.impl.LineReaderImpl.readLine(LineReaderImpl.java:476)
 at Main.main(Main.java:142)
Caused by: java.lang.IllegalArgumentException: Unknown signal: CONT
 at sun.misc.Signal.<init>(Signal.java:143)
 ... 10 more

Sep 15, 2017 10:57:42 AM org.jline.utils.Log logr
FINE: NonBlockingReader start
Sep 15, 2017 10:57:45 AM org.jline.utils.Log logr
FINEST: Binding: Reference[self-insert]
Sep 15, 2017 10:57:45 AM org.jline.utils.Log logr
FINEST: Binding: Reference[self-insert]
Sep 15, 2017 10:57:45 AM org.jline.utils.Log logr
FINEST: Binding: Reference[self-insert]
Sep 15, 2017 10:57:46 AM org.jline.utils.Log logr
FINEST: Binding: Reference[self-insert]
Sep 15, 2017 10:57:46 AM org.jline.utils.Log logr
FINEST: Binding: Reference[self-insert]
Sep 15, 2017 10:57:47 AM org.jline.utils.Log logr
FINEST: Binding: Reference[self-insert]
Sep 15, 2017 10:57:47 AM org.jline.utils.Log logr
FINEST: Binding: Reference[self-insert]
Sep 15, 2017 10:57:47 AM org.jline.utils.Log logr
FINEST: Binding: Reference[self-insert]
Sep 15, 2017 10:57:47 AM org.jline.utils.Log logr
FINEST: Binding: Reference[self-insert]
Sep 15, 2017 10:57:48 AM org.jline.utils.Log logr
FINEST: Binding: Reference[self-insert]
Sep 15, 2017 10:57:48 AM org.jline.utils.Log logr
FINEST: Binding: Reference[self-insert]
Sep 15, 2017 10:57:48 AM org.jline.utils.Log logr
FINEST: Binding: Reference[self-insert]
Sep 15, 2017 10:57:48 AM org.jline.utils.Log logr
FINEST: Binding: Reference[self-insert]
Sep 15, 2017 10:57:49 AM org.jline.utils.Log logr
FINEST: Binding: Reference[self-insert]
Sep 15, 2017 10:57:49 AM org.jline.utils.Log logr
FINEST: Binding: Reference[self-insert]
Sep 15, 2017 10:57:50 AM org.jline.utils.Log logr
FINEST: Binding: Reference[self-insert]
Sep 15, 2017 10:57:50 AM org.jline.utils.Log logr
FINEST: Binding: Reference[self-insert]
Sep 15, 2017 10:57:51 AM org.jline.utils.Log logr
FINEST: Binding: Reference[accept-line]
Sep 15, 2017 10:57:51 AM org.jline.utils.Log logr
FINEST: Registering signal INT with handler SIG_DFL
Sep 15, 2017 10:57:51 AM org.jline.utils.Log logr
FINEST: Registering signal WINCH with handler SIG_DFL
Sep 15, 2017 10:57:51 AM org.jline.utils.Log logr
FINE: Error registering default handler for signal WINCH
java.lang.reflect.InvocationTargetException
 at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
 at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
 at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
 at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
 at org.jline.utils.Signals.doRegister(Signals.java:94)
 at org.jline.utils.Signals.registerDefault(Signals.java:66)
 at org.jline.terminal.impl.AbstractWindowsTerminal.handle(AbstractWindowsTerminal.java:103)
 at org.jline.reader.impl.LineReaderImpl.readLine(LineReaderImpl.java:594)
 at Main.main(Main.java:142)
Caused by: java.lang.IllegalArgumentException: Unknown signal: WINCH
 at sun.misc.Signal.<init>(Signal.java:143)
 ... 9 more

Sep 15, 2017 10:57:51 AM org.jline.utils.Log logr
FINEST: Registering signal CONT with handler SIG_DFL
Sep 15, 2017 10:57:51 AM org.jline.utils.Log logr
FINE: Error registering default handler for signal CONT
java.lang.reflect.InvocationTargetException
 at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
 at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
 at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
 at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
 at org.jline.utils.Signals.doRegister(Signals.java:94)
 at org.jline.utils.Signals.registerDefault(Signals.java:66)
 at org.jline.terminal.impl.AbstractWindowsTerminal.handle(AbstractWindowsTerminal.java:103)
 at org.jline.reader.impl.LineReaderImpl.readLine(LineReaderImpl.java:597)
 at Main.main(Main.java:142)
Caused by: java.lang.IllegalArgumentException: Unknown signal: CONT
 at sun.misc.Signal.<init>(Signal.java:143)
 ... 9 more

Sep 15, 2017 10:57:51 AM org.jline.utils.Log logr
FINE: Removing shutdown-hook: Thread[JLine Shutdown Hook,5,main]
Sep 15, 2017 10:57:51 AM org.jline.utils.Log logr
FINE: NonBlockingReader shutdown
Sep 15, 2017 10:58:51 AM org.jline.utils.Log logr
FINE: Error creating JNA based terminal: [6] The handle is invalid.
com.sun.jna.LastErrorException: [6] The handle is invalid.
 at com.sun.jna.Native.invokeVoid(Native Method)
 at com.sun.jna.Function.invoke(Function.java:408)
 at com.sun.jna.Function.invoke(Function.java:354)
 at com.sun.jna.Library$Handler.invoke(Library.java:244)
 at org.jline.terminal.impl.jna.win.$Proxy0.GetConsoleScreenBufferInfo(Unknown Source)
 at org.jline.terminal.impl.jna.win.WindowsAnsiOutputStream.getConsoleInfo(WindowsAnsiOutputStream.java:92)
 at org.jline.terminal.impl.jna.win.WindowsAnsiOutputStream.<init>(WindowsAnsiOutputStream.java:86)
 at org.jline.terminal.impl.jna.win.JnaWinSysTerminal.<init>(JnaWinSysTerminal.java:38)
 at org.jline.terminal.impl.jna.JnaSupportImpl.winSysTerminal(JnaSupportImpl.java:25)
 at org.jline.terminal.TerminalBuilder.doBuild(TerminalBuilder.java:243)
 at org.jline.terminal.TerminalBuilder.build(TerminalBuilder.java:172)
 at Main.main(Main.java:32)

Sep 15, 2017 10:58:51 AM org.jline.utils.Log logr
FINE: Error creating JANSI based terminal: null
java.lang.UnsupportedOperationException
 at org.jline.terminal.impl.jansi.JansiSupportImpl.winSysTerminal(JansiSupportImpl.java:103)
 at org.jline.terminal.TerminalBuilder.doBuild(TerminalBuilder.java:251)
 at org.jline.terminal.TerminalBuilder.build(TerminalBuilder.java:172)
 at Main.main(Main.java:32)

Sep 15, 2017 10:58:51 AM org.jline.utils.Log logr
WARNING: Creating a dumb terminal
java.lang.IllegalStateException: Unable to create a system terminal
 at org.jline.terminal.TerminalBuilder.doBuild(TerminalBuilder.java:219)
 at org.jline.terminal.TerminalBuilder.build(TerminalBuilder.java:172)
 at Main.main(Main.java:32)
 Suppressed: com.sun.jna.LastErrorException: [6] The handle is invalid.
  at com.sun.jna.Native.invokeVoid(Native Method)
  at com.sun.jna.Function.invoke(Function.java:408)
  at com.sun.jna.Function.invoke(Function.java:354)
  at com.sun.jna.Library$Handler.invoke(Library.java:244)
  at org.jline.terminal.impl.jna.win.$Proxy0.GetConsoleScreenBufferInfo(Unknown Source)
  at org.jline.terminal.impl.jna.win.WindowsAnsiOutputStream.getConsoleInfo(WindowsAnsiOutputStream.java:92)
  at org.jline.terminal.impl.jna.win.WindowsAnsiOutputStream.<init>(WindowsAnsiOutputStream.java:86)
  at org.jline.terminal.impl.jna.win.JnaWinSysTerminal.<init>(JnaWinSysTerminal.java:38)
  at org.jline.terminal.impl.jna.JnaSupportImpl.winSysTerminal(JnaSupportImpl.java:25)
  at org.jline.terminal.TerminalBuilder.doBuild(TerminalBuilder.java:243)
  ... 2 more
 Suppressed: java.lang.UnsupportedOperationException
  at org.jline.terminal.impl.jansi.JansiSupportImpl.winSysTerminal(JansiSupportImpl.java:103)
  at org.jline.terminal.TerminalBuilder.doBuild(TerminalBuilder.java:251)
  ... 2 more

Sep 15, 2017 10:58:51 AM org.jline.utils.Log logr
FINE: Using terminal DumbTerminal
Sep 15, 2017 10:58:51 AM org.jline.utils.Log logr
FINE: NonBlockingReader start

/Users/Phil/Downloads/image-5.png

@PhVdP
Copy link
Author

PhVdP commented Sep 15, 2017

With the picture now:
image-5

@jline jline deleted a comment from PhVdP Sep 15, 2017
@gnodet
Copy link
Member

gnodet commented Sep 15, 2017

Could you build jline with the following patch 4166615 and see if it works better ?

@gnodet
Copy link
Member

gnodet commented Sep 19, 2017

The exception should not be a problem anymore now that we use the WriteConsoleW method instead of using the standard output stream.

@PhVdP
Copy link
Author

PhVdP commented Sep 19, 2017

capture3

As requested, JLine library rebuilt with the code provided in the branch specified for the patch 4166615. So, indeed the ouput stream seems ok in the subprocess and the terminal can be rebuilt at each loop. However, Jline is still interfering with the STDIN with the sub-process (and the terminal is closed !). So, the problem is not solved.

@PhVdP
Copy link
Author

PhVdP commented Sep 19, 2017

and the log:

Sep 19, 2017 1:07:29 PM org.jline.utils.Log logr
FINE: Registering shutdown-hook: Thread[JLine Shutdown Hook,5,main]
Sep 19, 2017 1:07:29 PM org.jline.utils.Log logr
FINE: Adding shutdown-hook task: org.jline.terminal.impl.AbstractWindowsTerminal$$Lambda$11/1937962514@3abfe836
Sep 19, 2017 1:07:29 PM org.jline.utils.Log logr
FINE: Using terminal JnaWinSysTerminal
Sep 19, 2017 1:07:29 PM org.jline.utils.Log logr
FINEST: Registering signal INT with handler org.jline.terminal.impl.AbstractWindowsTerminal$$Lambda$159/209813603@3cb5cdba
Sep 19, 2017 1:07:29 PM org.jline.utils.Log logr
FINEST: Registering signal WINCH with handler org.jline.terminal.impl.AbstractWindowsTerminal$$Lambda$159/209813603@d041cf
Sep 19, 2017 1:07:29 PM org.jline.utils.Log logr
FINE: Error registering handler for signal WINCH
java.lang.reflect.InvocationTargetException
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
	at org.jline.utils.Signals.doRegister(Signals.java:94)
	at org.jline.utils.Signals.register(Signals.java:55)
	at org.jline.utils.Signals.register(Signals.java:35)
	at org.jline.terminal.impl.AbstractWindowsTerminal.handle(AbstractWindowsTerminal.java:137)
	at org.jline.reader.impl.LineReaderImpl.readLine(LineReaderImpl.java:479)
	at org.jline.reader.impl.LineReaderImpl.readLine(LineReaderImpl.java:426)
	at Main.main(Main.java:146)
Caused by: java.lang.IllegalArgumentException: Unknown signal: WINCH
	at sun.misc.Signal.<init>(Signal.java:143)
	... 11 more

Sep 19, 2017 1:07:29 PM org.jline.utils.Log logr
FINEST: Registering signal CONT with handler org.jline.terminal.impl.AbstractWindowsTerminal$$Lambda$159/209813603@2d209079
Sep 19, 2017 1:07:29 PM org.jline.utils.Log logr
FINE: Error registering handler for signal CONT
java.lang.reflect.InvocationTargetException
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
	at org.jline.utils.Signals.doRegister(Signals.java:94)
	at org.jline.utils.Signals.register(Signals.java:55)
	at org.jline.utils.Signals.register(Signals.java:35)
	at org.jline.terminal.impl.AbstractWindowsTerminal.handle(AbstractWindowsTerminal.java:137)
	at org.jline.reader.impl.LineReaderImpl.readLine(LineReaderImpl.java:480)
	at org.jline.reader.impl.LineReaderImpl.readLine(LineReaderImpl.java:426)
	at Main.main(Main.java:146)
Caused by: java.lang.IllegalArgumentException: Unknown signal: CONT
	at sun.misc.Signal.<init>(Signal.java:143)
	... 11 more

Sep 19, 2017 1:07:29 PM org.jline.utils.Log logr
FINE: NonBlockingReader start
Sep 19, 2017 1:07:33 PM org.jline.utils.Log logr
FINEST: Binding: Reference[self-insert]
Sep 19, 2017 1:07:33 PM org.jline.utils.Log logr
FINEST: Binding: Reference[self-insert]
Sep 19, 2017 1:07:33 PM org.jline.utils.Log logr
FINEST: Binding: Reference[self-insert]
Sep 19, 2017 1:07:33 PM org.jline.utils.Log logr
FINEST: Binding: Reference[self-insert]
Sep 19, 2017 1:07:34 PM org.jline.utils.Log logr
FINEST: Binding: Reference[accept-line]
Sep 19, 2017 1:07:34 PM org.jline.utils.Log logr
FINEST: Registering signal INT with handler SIG_DFL
Sep 19, 2017 1:07:34 PM org.jline.utils.Log logr
FINEST: Registering signal WINCH with handler SIG_DFL
Sep 19, 2017 1:07:34 PM org.jline.utils.Log logr
FINE: Error registering default handler for signal WINCH
java.lang.reflect.InvocationTargetException
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
	at org.jline.utils.Signals.doRegister(Signals.java:94)
	at org.jline.utils.Signals.registerDefault(Signals.java:66)
	at org.jline.terminal.impl.AbstractWindowsTerminal.handle(AbstractWindowsTerminal.java:135)
	at org.jline.reader.impl.LineReaderImpl.readLine(LineReaderImpl.java:598)
	at org.jline.reader.impl.LineReaderImpl.readLine(LineReaderImpl.java:426)
	at Main.main(Main.java:146)
Caused by: java.lang.IllegalArgumentException: Unknown signal: WINCH
	at sun.misc.Signal.<init>(Signal.java:143)
	... 10 more

Sep 19, 2017 1:07:34 PM org.jline.utils.Log logr
FINEST: Registering signal CONT with handler SIG_DFL
Sep 19, 2017 1:07:34 PM org.jline.utils.Log logr
FINE: Error registering default handler for signal CONT
java.lang.reflect.InvocationTargetException
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
	at org.jline.utils.Signals.doRegister(Signals.java:94)
	at org.jline.utils.Signals.registerDefault(Signals.java:66)
	at org.jline.terminal.impl.AbstractWindowsTerminal.handle(AbstractWindowsTerminal.java:135)
	at org.jline.reader.impl.LineReaderImpl.readLine(LineReaderImpl.java:601)
	at org.jline.reader.impl.LineReaderImpl.readLine(LineReaderImpl.java:426)
	at Main.main(Main.java:146)
Caused by: java.lang.IllegalArgumentException: Unknown signal: CONT
	at sun.misc.Signal.<init>(Signal.java:143)
	... 10 more

Sep 19, 2017 1:07:34 PM org.jline.utils.Log logr
FINE: Removing shutdown-hook: Thread[JLine Shutdown Hook,5,main]
Sep 19, 2017 1:07:34 PM org.jline.utils.Log logr
FINE: NonBlockingReader shutdown
Sep 19, 2017 1:07:34 PM org.jline.utils.Log logr
FINE: Registering shutdown-hook: Thread[JLine Shutdown Hook,5,main]
Sep 19, 2017 1:07:34 PM org.jline.utils.Log logr
FINE: Adding shutdown-hook task: org.jline.terminal.impl.AbstractWindowsTerminal$$Lambda$11/1937962514@506e6d5e
Sep 19, 2017 1:07:34 PM org.jline.utils.Log logr
FINE: Using terminal JnaWinSysTerminal
Sep 19, 2017 1:07:34 PM org.jline.utils.Log logr
FINEST: Registering signal INT with handler org.jline.terminal.impl.AbstractWindowsTerminal$$Lambda$159/209813603@96532d6
Sep 19, 2017 1:07:34 PM org.jline.utils.Log logr
FINEST: Registering signal WINCH with handler org.jline.terminal.impl.AbstractWindowsTerminal$$Lambda$159/209813603@3796751b
Sep 19, 2017 1:07:34 PM org.jline.utils.Log logr
FINE: Error registering handler for signal WINCH
java.lang.reflect.InvocationTargetException
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
	at org.jline.utils.Signals.doRegister(Signals.java:94)
	at org.jline.utils.Signals.register(Signals.java:55)
	at org.jline.utils.Signals.register(Signals.java:35)
	at org.jline.terminal.impl.AbstractWindowsTerminal.handle(AbstractWindowsTerminal.java:137)
	at org.jline.reader.impl.LineReaderImpl.readLine(LineReaderImpl.java:479)
	at org.jline.reader.impl.LineReaderImpl.readLine(LineReaderImpl.java:426)
	at Main.main(Main.java:146)
Caused by: java.lang.IllegalArgumentException: Unknown signal: WINCH
	at sun.misc.Signal.<init>(Signal.java:143)
	... 11 more

Sep 19, 2017 1:07:34 PM org.jline.utils.Log logr
FINEST: Registering signal CONT with handler org.jline.terminal.impl.AbstractWindowsTerminal$$Lambda$159/209813603@6442b0a6
Sep 19, 2017 1:07:34 PM org.jline.utils.Log logr
FINE: Error registering handler for signal CONT
java.lang.reflect.InvocationTargetException
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
	at org.jline.utils.Signals.doRegister(Signals.java:94)
	at org.jline.utils.Signals.register(Signals.java:55)
	at org.jline.utils.Signals.register(Signals.java:35)
	at org.jline.terminal.impl.AbstractWindowsTerminal.handle(AbstractWindowsTerminal.java:137)
	at org.jline.reader.impl.LineReaderImpl.readLine(LineReaderImpl.java:480)
	at org.jline.reader.impl.LineReaderImpl.readLine(LineReaderImpl.java:426)
	at Main.main(Main.java:146)
Caused by: java.lang.IllegalArgumentException: Unknown signal: CONT
	at sun.misc.Signal.<init>(Signal.java:143)
	... 11 more

Sep 19, 2017 1:07:34 PM org.jline.utils.Log logr
FINE: NonBlockingReader start
Sep 19, 2017 1:07:42 PM org.jline.utils.Log logr
FINEST: Binding: Reference[self-insert]
Sep 19, 2017 1:07:43 PM org.jline.utils.Log logr
FINEST: Binding: Reference[self-insert]
Sep 19, 2017 1:07:43 PM org.jline.utils.Log logr
FINEST: Binding: Reference[self-insert]
Sep 19, 2017 1:07:43 PM org.jline.utils.Log logr
FINEST: Binding: Reference[self-insert]
Sep 19, 2017 1:07:43 PM org.jline.utils.Log logr
FINEST: Binding: Reference[self-insert]
Sep 19, 2017 1:07:45 PM org.jline.utils.Log logr
FINEST: Binding: Reference[self-insert]
Sep 19, 2017 1:07:46 PM org.jline.utils.Log logr
FINEST: Binding: Reference[self-insert]
Sep 19, 2017 1:07:46 PM org.jline.utils.Log logr
FINEST: Binding: Reference[self-insert]
Sep 19, 2017 1:07:47 PM org.jline.utils.Log logr
FINEST: Binding: Reference[self-insert]
Sep 19, 2017 1:07:47 PM org.jline.utils.Log logr
FINEST: Binding: Reference[self-insert]
Sep 19, 2017 1:07:47 PM org.jline.utils.Log logr
FINEST: Binding: Reference[self-insert]
Sep 19, 2017 1:07:47 PM org.jline.utils.Log logr
FINEST: Binding: Reference[self-insert]
Sep 19, 2017 1:07:48 PM org.jline.utils.Log logr
FINEST: Binding: Reference[self-insert]
Sep 19, 2017 1:07:48 PM org.jline.utils.Log logr
FINEST: Binding: Reference[self-insert]
Sep 19, 2017 1:07:49 PM org.jline.utils.Log logr
FINEST: Binding: Reference[self-insert]
Sep 19, 2017 1:07:49 PM org.jline.utils.Log logr
FINEST: Binding: Reference[self-insert]
Sep 19, 2017 1:07:49 PM org.jline.utils.Log logr
FINEST: Binding: Reference[self-insert]
Sep 19, 2017 1:07:50 PM org.jline.utils.Log logr
FINEST: Binding: Reference[accept-line]
Sep 19, 2017 1:07:50 PM org.jline.utils.Log logr
FINEST: Registering signal INT with handler SIG_DFL
Sep 19, 2017 1:07:50 PM org.jline.utils.Log logr
FINEST: Registering signal WINCH with handler SIG_DFL
Sep 19, 2017 1:07:50 PM org.jline.utils.Log logr
FINE: Error registering default handler for signal WINCH
java.lang.reflect.InvocationTargetException
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
	at org.jline.utils.Signals.doRegister(Signals.java:94)
	at org.jline.utils.Signals.registerDefault(Signals.java:66)
	at org.jline.terminal.impl.AbstractWindowsTerminal.handle(AbstractWindowsTerminal.java:135)
	at org.jline.reader.impl.LineReaderImpl.readLine(LineReaderImpl.java:598)
	at org.jline.reader.impl.LineReaderImpl.readLine(LineReaderImpl.java:426)
	at Main.main(Main.java:146)
Caused by: java.lang.IllegalArgumentException: Unknown signal: WINCH
	at sun.misc.Signal.<init>(Signal.java:143)
	... 10 more

Sep 19, 2017 1:07:50 PM org.jline.utils.Log logr
FINEST: Registering signal CONT with handler SIG_DFL
Sep 19, 2017 1:07:50 PM org.jline.utils.Log logr
FINE: Error registering default handler for signal CONT
java.lang.reflect.InvocationTargetException
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
	at org.jline.utils.Signals.doRegister(Signals.java:94)
	at org.jline.utils.Signals.registerDefault(Signals.java:66)
	at org.jline.terminal.impl.AbstractWindowsTerminal.handle(AbstractWindowsTerminal.java:135)
	at org.jline.reader.impl.LineReaderImpl.readLine(LineReaderImpl.java:601)
	at org.jline.reader.impl.LineReaderImpl.readLine(LineReaderImpl.java:426)
	at Main.main(Main.java:146)
Caused by: java.lang.IllegalArgumentException: Unknown signal: CONT
	at sun.misc.Signal.<init>(Signal.java:143)
	... 10 more

Sep 19, 2017 1:07:50 PM org.jline.utils.Log logr
FINE: Removing shutdown-hook: Thread[JLine Shutdown Hook,5,main]
Sep 19, 2017 1:07:50 PM org.jline.utils.Log logr
FINE: NonBlockingReader shutdown

@gnodet
Copy link
Member

gnodet commented Sep 20, 2017

I've just tried the following code.

package org.jline.demo;

import org.jline.reader.EndOfFileException;
import org.jline.reader.LineReader;
import org.jline.reader.LineReaderBuilder;
import org.jline.reader.ParsedLine;
import org.jline.reader.UserInterruptException;
import org.jline.reader.impl.history.DefaultHistory;
import org.jline.terminal.Terminal;
import org.jline.terminal.TerminalBuilder;

import java.io.IOException;
import java.util.Locale;
import java.util.concurrent.TimeUnit;

public class Test {

    public static void main(String[] args) {
        try {
            while (true) {
                ParsedLine line = readLine("prompt> ");
                if (line == null) {
                    return;
                }
                String cmd = line.words().get(0).toLowerCase(Locale.ENGLISH);
                switch (cmd) {
                    case "quit":
                    case "exit":
                        return;
                    default:
                        runCommand(line);
                        break;
                }
            }
        } catch (Throwable t) {
            t.printStackTrace();
        }
    }

    private static LineReaderBuilder lineReaderBuilder = LineReaderBuilder.builder();

    private static ParsedLine readLine(String prompt) throws IOException {
        try (Terminal terminal = TerminalBuilder.terminal()) {
            LineReader reader = lineReaderBuilder
                    .terminal(terminal)
                    .build();
            while (true) {
                try {
                    String line = reader.readLine(prompt);
                    if (line == null) {
                        break;
                    }
                    line = line.trim();
                    if (!line.isEmpty()) {
                        terminal.writer().println("======>\"" + line + "\"");
                        terminal.flush();
                        return reader.getParsedLine();
                    }
                } catch (UserInterruptException e) {
                    terminal.writer().println("User Interruption !");
                } catch (EndOfFileException e) {
                    break;
                }
            }
            return null;
        }
    }

    private static int runCommand(ParsedLine command) {
        int returnCode = -1;
        try {
            ProcessBuilder pb = new ProcessBuilder(command.words());
            pb.inheritIO();
            Process p = pb.start();
            if (!p.waitFor(60, TimeUnit.SECONDS))
                System.out.println("Timeout");
            else {
                returnCode = p.exitValue();
                System.out.println("return code :" + returnCode);
            }
            return returnCode;
        } catch (Throwable t) {
            t.printStackTrace();
            returnCode = -1;
        }
        return returnCode;
    }

}

I've tried it with jansi and latest jline and it's working without any problems for me when running a simple batch file containing echo Test.

@PhVdP
Copy link
Author

PhVdP commented Sep 21, 2017

It works fine with the echo test for me too (;o). Stdout is ok for the subprocess however it is not the case for the stdin. Have you try to re-launch your small java test application (a second time) from it ?

@gnodet
Copy link
Member

gnodet commented Sep 21, 2017

I just did and it works fine for me.

test-jline

@PhVdP
Copy link
Author

PhVdP commented Sep 22, 2017

Hi,

Still not working for me, specially with the perl script. I've slightly updated your code to display the Windows console mode for the input and output buffers of the console. I tries with the two implementations: jna and jansi and for both I've the following result:
capturea1

At the start of the application, the console mode of the input buffer = 423 in decimal, but when calling the subprocess, value is 14 in decimal. I guess that perl which inherites the (Std)IOs, does not update the console input buffer mode. In fact, at the execution of the script, the chars are currently managed by the perl application but the CR/LF is trapped by the Jline in java application...

I've update the code again to change the input buffer console mode to the initial value before calling the subprocess, and the result is now OK.

capturea2

		java.util.logging.FileHandler fh = new java.util.logging.FileHandler ("jline.log");
			fh.setFormatter(new java.util.logging.SimpleFormatter ());
			Logger.getLogger("org.jline").addHandler(fh);
			Logger.getLogger("org.jline").setLevel(java.util.logging.Level.ALL);

			/* read the console mode */
			IntByReference init_mode_in = new IntByReference();
			Kernel32.INSTANCE.GetConsoleMode(consoleIn, init_mode_in);
			System.out.println("in :" + init_mode_in.getValue());

			IntByReference init_mode_out = new IntByReference();
			Kernel32.INSTANCE.GetConsoleMode(consoleOut, init_mode_out);
			System.out.println("out :" + init_mode_out.getValue());

			while (true) {
				ParsedLine line = readLine("prompt> ");
				if (line == null) {
					return;
				}
				String cmd = line.words().get(0).toLowerCase(Locale.ENGLISH);
				switch (cmd) {
				case "quit":
				case "exit":
					return;
				default:
					IntByReference mode = new IntByReference();
					Kernel32.INSTANCE.GetConsoleMode(consoleIn, mode);
					System.out.println("in :" + mode.getValue());
					
					IntByReference mode_out = new IntByReference();
					Kernel32.INSTANCE.GetConsoleMode(consoleOut, mode_out);
					System.out.println("out :" + mode_out.getValue());
				    
					Kernel32.INSTANCE.SetConsoleMode(consoleIn, init_mode_in.getValue());
					
					mode = new IntByReference();
					Kernel32.INSTANCE.GetConsoleMode(consoleIn, mode);
					System.out.println("in :" + mode.getValue());
					
			
					runCommand(line);
					break;
				}
			}
		} catch (Throwable t) {
			t.printStackTrace();
		}
	}

gnodet added a commit to gnodet/jline3 that referenced this issue Sep 22, 2017
@gnodet
Copy link
Member

gnodet commented Sep 22, 2017

Could you verify that the following commit gnodet@f8eda07 fixes your issue ?

@PhVdP
Copy link
Author

PhVdP commented Sep 27, 2017

Hi,

Due to time constraint, I was not able to test the latest version of your library but if it includes a mechanism to save the input console mode (from the start of the application) to be restore when calling the subprocess and reverse (meaning to restore the input console mode when back from the process execution with the value saved before execution), I guess part of the issue will be solved.

I've integrate a patch like explained in the previous paragraph to our application but in some cases, the subprocess was still frozen and sometime part of the password characters typing in the subprocess is appearing in clear in the main application using jline. This bug is not acceptable...

Further to my investigation in the library, I made a test where I remove the NonBlockingReader with a classical reader, This reader calls the 'process event' from the queue of STDIN. Foloowing some tests done so far, it seems, for the functionality that I need for my application are affected by this bloking readng, and the application + jline without the windows 'pump thread' seem to work better - windows is already managing an input buffer per porcess for us...

I give you some copy of codes about this test done. I would to know if a parameter can be defined somewhere to start jline in a 'single reading' thread. This will certainly help resolving the issue #140 also.

` This class wraps a regular reader and allows it to appear as if it

  • is non-blocking; that is, reads can be performed against it that timeout
  • if no data is seen for a period of time. This effect is achieved by having
  • a separate thread perform all non-blocking read requests and then
  • waiting on the thread to complete.
  • VERY IMPORTANT NOTES

    • **# This class is not thread safe. It expects at most one reader.**
    • The {@link #shutdown()} method must be called in order to shut down
    •      the thread that handles blocking I/O.`
      

    As explain in the header of the NonBlockingReader, only one reader is expected and the confiugration of our subprocess, which inherits frm the stdin, concurrent reader is there...

    `//PumpReader reader = new PumpReader();
    //this.slaveInputPipe = reader.getWriter();
    //this.reader = new NonBlockingReader(getName(), reader);

        this.reader = new Reader () {
            public int read (char[] b, int off, int len) throws IOException {
                if (b == null) {
                    throw new NullPointerException();
                } else if (off < 0 || len < 0 || len > b.length - off) {
                    throw new IndexOutOfBoundsException();
                } else if (len == 0) {
                    return 0;
                }
    
                while (true) {
                  readingChar = (char) 0;
                  processConsoleInput ();
                
                  int i = (int) readingChar;
                  
                  if (i == -1) {
                    return -1;
                  }
                  
                  if (i == 0) {
                	  try {
    					Thread.sleep (100);
    				} catch (InterruptedException e) {
    					// TODO Auto-generated catch block
    					//e.printStackTrace();
    				}
                	  continue;
                  }
                  else {
                	  break;
                  }
                }
                
                b[off] = (char)readingChar;
                return 1;
              }
    
            
    		@Override
    		public void close() throws IOException {
    			// TODO Auto-generated method stub
    		  //Close the reader	
    		}
        };`
    

    pump = new Thread(this::pump, "WindowsStreamPump"); pump.setDaemon(true); // This is called by the JNA/Jansi terminal implementation to avoid // race conditions if they do initialization in their constructor //pump.start();*/

    and in the Terminal interface:
    //NonBlockingReader reader();
    Reader reader ();

@sake92
Copy link

sake92 commented Sep 2, 2021

@gnodet
Copy link
Member

gnodet commented Sep 2, 2021

@gnodet Sorry to spam a closed issue, but can this be relevant?

https://stackoverflow.com/a/377154/4496364
https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea#consoles

So, instead of these: https://github.com/jline/jline3/blob/master/terminal-jna/src/main/java/org/jline/terminal/impl/jna/win/JnaWinSysTerminal.java#L28-L29

it would be something like
Kernel32.CreateFile("CONIN$",...

@sake92 Not sure this is related to this issue. This would be more about getting the correct handle if the input or output is redirected, right ? But I agree, this would seem a better solution in case of a redirect. Feel free to raise a new JIRA, but we need to investigate the exact behavior wanted and find a solution for osx / linux.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants