Skip to content

Commit

Permalink
Track the system terminal, fixes #508
Browse files Browse the repository at this point in the history
  • Loading branch information
gnodet committed Feb 28, 2020
1 parent 1362e89 commit c3317bc
Show file tree
Hide file tree
Showing 9 changed files with 68 additions and 29 deletions.
4 changes: 2 additions & 2 deletions builtins/src/main/java/org/jline/builtins/Tmux.java
Original file line number Diff line number Diff line change
Expand Up @@ -1865,8 +1865,8 @@ public void write(int b) throws IOException {
masterOutput,
null) {
@Override
public void close() throws IOException {
super.close();
protected void doClose() throws IOException {
super.doClose();
closer.accept(VirtualConsole.this);
}
};
Expand Down
52 changes: 38 additions & 14 deletions terminal/src/main/java/org/jline/terminal/TerminalBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@
import java.nio.charset.UnsupportedCharsetException;
import java.util.Optional;
import java.util.ServiceLoader;
import java.util.concurrent.atomic.AtomicReference;

import org.jline.terminal.impl.AbstractPosixTerminal;
import org.jline.terminal.impl.AbstractTerminal;
import org.jline.terminal.impl.DumbTerminal;
import org.jline.terminal.impl.ExecPty;
import org.jline.terminal.impl.ExternalTerminal;
Expand Down Expand Up @@ -84,6 +86,8 @@ public static TerminalBuilder builder() {
return new TerminalBuilder();
}

private static final AtomicReference<Terminal> SYSTEM_TERMINAL = new AtomicReference<>();

private String name;
private InputStream in;
private OutputStream out;
Expand Down Expand Up @@ -311,6 +315,7 @@ private Terminal doBuild() throws IOException {
Log.warn("Attributes and size fields are ignored when creating a system terminal");
}
IllegalStateException exception = new IllegalStateException("Unable to create a system terminal");
Terminal terminal = null;
if (OSUtils.IS_WINDOWS) {
boolean cygwinTerm = "cygwin".equals(System.getenv("TERM"));
boolean ansiPassThrough = OSUtils.IS_CONEMU;
Expand All @@ -325,61 +330,78 @@ private Terminal doBuild() throws IOException {
if ("xterm".equals(type) && this.type == null && System.getProperty(PROP_TYPE) == null) {
type = "xterm-256color";
}
return new PosixSysTerminal(name, type, pty, encoding, nativeSignals, signalHandler);
terminal = new PosixSysTerminal(name, type, pty, encoding, nativeSignals, signalHandler);
} catch (IOException e) {
// Ignore if not a tty
Log.debug("Error creating EXEC based terminal: ", e.getMessage(), e);
exception.addSuppressed(e);
}
}
if (jna) {
if (terminal == null && jna) {
try {
return load(JnaSupport.class).winSysTerminal(name, type, ansiPassThrough, encoding, codepage, nativeSignals, signalHandler, paused);
terminal = load(JnaSupport.class).winSysTerminal(name, type, ansiPassThrough, encoding, codepage, nativeSignals, signalHandler, paused);
} catch (Throwable t) {
Log.debug("Error creating JNA based terminal: ", t.getMessage(), t);
exception.addSuppressed(t);
}
}
if (jansi) {
if (terminal == null && jansi) {
try {
return load(JansiSupport.class).winSysTerminal(name, type, ansiPassThrough, encoding, codepage, nativeSignals, signalHandler, paused);
terminal = load(JansiSupport.class).winSysTerminal(name, type, ansiPassThrough, encoding, codepage, nativeSignals, signalHandler, paused);
} catch (Throwable t) {
Log.debug("Error creating JANSI based terminal: ", t.getMessage(), t);
exception.addSuppressed(t);
}
}
} else {
if (jna) {
if (terminal == null && jna) {
try {
Pty pty = load(JnaSupport.class).current();
return new PosixSysTerminal(name, type, pty, encoding, nativeSignals, signalHandler);
terminal = new PosixSysTerminal(name, type, pty, encoding, nativeSignals, signalHandler);
} catch (Throwable t) {
// ignore
Log.debug("Error creating JNA based terminal: ", t.getMessage(), t);
exception.addSuppressed(t);
}
}
if (jansi) {
if (terminal == null && jansi) {
try {
Pty pty = load(JansiSupport.class).current();
return new PosixSysTerminal(name, type, pty, encoding, nativeSignals, signalHandler);
terminal = new PosixSysTerminal(name, type, pty, encoding, nativeSignals, signalHandler);
} catch (Throwable t) {
Log.debug("Error creating JANSI based terminal: ", t.getMessage(), t);
exception.addSuppressed(t);
}
}
if (exec) {
if (terminal == null && exec) {
try {
Pty pty = ExecPty.current();
return new PosixSysTerminal(name, type, pty, encoding, nativeSignals, signalHandler);
terminal = new PosixSysTerminal(name, type, pty, encoding, nativeSignals, signalHandler);
} catch (Throwable t) {
// Ignore if not a tty
Log.debug("Error creating EXEC based terminal: ", t.getMessage(), t);
exception.addSuppressed(t);
}
}
}
if (dumb == null || dumb) {
if (terminal instanceof AbstractTerminal) {
AbstractTerminal t = (AbstractTerminal) terminal;
if (SYSTEM_TERMINAL.compareAndSet(null, t)) {
t.setOnClose(new Runnable() {
@Override
public void run() {
SYSTEM_TERMINAL.compareAndSet(t, null);
}
});
} else {
exception.addSuppressed(new IllegalStateException("A system terminal is already running. " +
"Make sure to use the created system Terminal on the LineReaderBuilder if you're using one " +
"or that previously created system Terminals have been correctly closed."));
terminal.close();
terminal = null;
}
}
if (terminal == null && (dumb == null || dumb)) {
// forced colored dumb terminal
boolean color = getBoolean(PROP_DUMB_COLOR, false);
// detect emacs using the env variable
Expand All @@ -398,13 +420,15 @@ private Terminal doBuild() throws IOException {
Log.warn("Unable to create a system terminal, creating a dumb terminal (enable debug logging for more information)");
}
}
return new DumbTerminal(name, color ? Terminal.TYPE_DUMB_COLOR : Terminal.TYPE_DUMB,
terminal = new DumbTerminal(name, color ? Terminal.TYPE_DUMB_COLOR : Terminal.TYPE_DUMB,
new FileInputStream(FileDescriptor.in),
new FileOutputStream(FileDescriptor.out),
encoding, signalHandler);
} else {
}
if (terminal == null) {
throw exception;
}
return terminal;
} else {
if (jna) {
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@ public void setSize(Size size) {
}
}

public void close() throws IOException {
super.close();
protected void doClose() throws IOException {
super.doClose();
pty.setAttr(originalAttributes);
pty.close();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ public abstract class AbstractTerminal implements Terminal {
protected final Map<Capability, Integer> ints = new HashMap<>();
protected final Map<Capability, String> strings = new HashMap<>();
protected Status status;
protected Runnable onClose;

public AbstractTerminal(String name, String type) throws IOException {
this(name, type, null, SignalHandler.SIG_DFL);
Expand All @@ -57,6 +58,10 @@ public AbstractTerminal(String name, String type, Charset encoding, SignalHandle
}
}

public void setOnClose(Runnable onClose) {
this.onClose = onClose;
}

public Status getStatus() {
return getStatus(true);
}
Expand Down Expand Up @@ -85,7 +90,17 @@ public void raise(Signal signal) {
}
}

public void close() throws IOException {
public final void close() throws IOException {
try {
doClose();
} finally {
if (onClose != null) {
onClose.run();
}
}
}

protected void doClose() throws IOException {
if (status != null) {
status.update(null);
flush();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -213,8 +213,8 @@ public void setSize(Size size) {
throw new UnsupportedOperationException("Can not resize windows terminal");
}

public void close() throws IOException {
super.close();
protected void doClose() throws IOException {
super.doClose();
closing = true;
if (pump != null) {
pump.interrupt();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,10 @@ public ExternalTerminal(String name, String type,
}
}

public void close() throws IOException {
protected void doClose() throws IOException {
if (closed.compareAndSet(false, true)) {
pause();
super.close();
super.doClose();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -257,8 +257,8 @@ protected void processIOException(IOException ioException) {
this.slaveInput.setIoException(ioException);
}

public void close() throws IOException {
super.close();
protected void doClose() throws IOException {
super.doClose();
try {
slaveReader.close();
} finally {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,8 @@ public PrintWriter writer() {
}

@Override
public void close() throws IOException {
super.close();
protected void doClose() throws IOException {
super.doClose();
reader.close();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,12 +87,12 @@ public OutputStream output() {
}

@Override
public void close() throws IOException {
protected void doClose() throws IOException {
ShutdownHooks.remove(closer);
for (Map.Entry<Signal, Object> entry : nativeHandlers.entrySet()) {
Signals.unregister(entry.getKey().name(), entry.getValue());
}
super.close();
super.doClose();
// Do not call reader.close()
reader.shutdown();
}
Expand Down

0 comments on commit c3317bc

Please sign in to comment.