Skip to content

Commit

Permalink
Crash on SIGTSTP (ctrl-Z) with native signals, fixes #59
Browse files Browse the repository at this point in the history
  • Loading branch information
gnodet committed Dec 9, 2016
1 parent 27e231c commit 65d06a0
Show file tree
Hide file tree
Showing 3 changed files with 129 additions and 6 deletions.
29 changes: 27 additions & 2 deletions src/main/java/org/jline/terminal/impl/AbstractWindowsTerminal.java
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,18 @@ public AbstractWindowsTerminal(OutputStream output, String name, boolean nativeS
attributes.setControlChar(Attributes.ControlChar.VSUSP, ctrl('Z'));
// Handle signals
if (nativeSignals) {
for (final Signal signal : Signal.values()) {
nativeHandlers.put(signal, Signals.register(signal.name(), () -> raise(signal)));
if (signalHandler == SignalHandler.SIG_DFL) {
for (final Signal signal : Signal.values()) {
Signals.registerDefault(signal.name());
}
} else if (signalHandler == SignalHandler.SIG_IGN) {
for (final Signal signal : Signal.values()) {
Signals.registerIgnore(signal.name());
}
} else {
for (final Signal signal : Signal.values()) {
nativeHandlers.put(signal, Signals.register(signal.name(), () -> raise(signal)));
}
}
}
pump = new Thread(this::pump, "WindowsStreamPump");
Expand All @@ -86,6 +96,21 @@ public AbstractWindowsTerminal(OutputStream output, String name, boolean nativeS
ShutdownHooks.add(closer);
}

@Override
public SignalHandler handle(Signal signal, SignalHandler handler) {
SignalHandler prev = super.handle(signal, handler);
if (handler == SignalHandler.SIG_DFL) {
Signals.registerDefault(signal.name());
nativeHandlers.remove(signal);
} else if (handler == SignalHandler.SIG_IGN) {
Signals.registerIgnore(signal.name());
nativeHandlers.remove(signal);
} else {
nativeHandlers.put(signal, Signals.register(signal.name(), () -> raise(signal)));
}
return prev;
}

@Override
protected void handleDefaultSignal(Signal signal) {
Object handler = nativeHandlers.get(signal);
Expand Down
33 changes: 29 additions & 4 deletions src/main/java/org/jline/terminal/impl/PosixSysTerminal.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,23 +33,48 @@ public class PosixSysTerminal extends AbstractPosixTerminal {
protected final Task closer;

public PosixSysTerminal(String name, String type, Pty pty, String encoding,
boolean nativeSignals, SignalHandler nativeSignalHandler) throws IOException {
super(name, type, pty);
boolean nativeSignals, SignalHandler signalHandler) throws IOException {
super(name, type, pty, signalHandler);
Objects.requireNonNull(encoding);
this.input = pty.getSlaveInput();
this.output = pty.getSlaveOutput();
this.reader = new NonBlockingReader(getName(), new InputStreamReader(input, encoding));
this.writer = new PrintWriter(new OutputStreamWriter(output, encoding));
parseInfoCmp();
if (nativeSignals) {
for (final Signal signal : Signal.values()) {
nativeHandlers.put(signal, Signals.register(signal.name(), () -> raise(signal)));
if (signalHandler == SignalHandler.SIG_DFL) {
for (final Signal signal : Signal.values()) {
Signals.registerDefault(signal.name());
}
} else if (signalHandler == SignalHandler.SIG_IGN) {
for (final Signal signal : Signal.values()) {
Signals.registerIgnore(signal.name());
}
} else {
for (final Signal signal : Signal.values()) {
nativeHandlers.put(signal, Signals.register(signal.name(), () -> raise(signal)));
}
}
}
closer = PosixSysTerminal.this::close;
ShutdownHooks.add(closer);
}

@Override
public SignalHandler handle(Signal signal, SignalHandler handler) {
SignalHandler prev = super.handle(signal, handler);
if (handler == SignalHandler.SIG_DFL) {
Signals.registerDefault(signal.name());
nativeHandlers.remove(signal);
} else if (handler == SignalHandler.SIG_IGN) {
Signals.registerIgnore(signal.name());
nativeHandlers.remove(signal);
} else {
nativeHandlers.put(signal, Signals.register(signal.name(), () -> raise(signal)));
}
return prev;
}

@Override
protected void handleDefaultSignal(Signal signal) {
Object handler = nativeHandlers.get(signal);
Expand Down
73 changes: 73 additions & 0 deletions src/test/java/org/jline/terminal/impl/PosixSysTerminalTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
* Copyright (c) 2002-2016, the original author or authors.
*
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
* http://www.opensource.org/licenses/bsd-license.php
*/
package org.jline.terminal.impl;

import org.easymock.EasyMock;
import org.jline.terminal.Attributes;
import org.jline.terminal.Terminal.Signal;
import org.jline.terminal.Terminal.SignalHandler;
import org.junit.Test;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.nio.charset.Charset;

import static org.junit.Assert.assertEquals;

public class PosixSysTerminalTest {

@Test
public void testNativeSignalsDefault() throws Exception {
Pty pty = EasyMock.createNiceMock(Pty.class);
EasyMock.expect(pty.getAttr()).andReturn(new Attributes()).anyTimes();
EasyMock.expect(pty.getSlaveInput()).andReturn(new ByteArrayInputStream(new byte[0])).anyTimes();
EasyMock.expect(pty.getSlaveOutput()).andReturn(new ByteArrayOutputStream()).anyTimes();
EasyMock.replay(pty);
try (PosixSysTerminal terminal = new PosixSysTerminal(
"name", "ansi", pty,
Charset.defaultCharset().name(), true,
SignalHandler.SIG_DFL)) {
assertEquals(0, terminal.nativeHandlers.size());
}
}

@Test
public void testNativeSignalsIgnore() throws Exception {
Pty pty = EasyMock.createNiceMock(Pty.class);
EasyMock.expect(pty.getAttr()).andReturn(new Attributes()).anyTimes();
EasyMock.expect(pty.getSlaveInput()).andReturn(new ByteArrayInputStream(new byte[0])).anyTimes();
EasyMock.expect(pty.getSlaveOutput()).andReturn(new ByteArrayOutputStream()).anyTimes();
EasyMock.replay(pty);
try (PosixSysTerminal terminal = new PosixSysTerminal(
"name", "ansi", pty,
Charset.defaultCharset().name(), true,
SignalHandler.SIG_IGN)) {
assertEquals(0, terminal.nativeHandlers.size());
}
}

@Test
public void testNativeSignalsRegister() throws Exception {
Pty pty = EasyMock.createNiceMock(Pty.class);
EasyMock.expect(pty.getAttr()).andReturn(new Attributes()).anyTimes();
EasyMock.expect(pty.getSlaveInput()).andReturn(new ByteArrayInputStream(new byte[0])).anyTimes();
EasyMock.expect(pty.getSlaveOutput()).andReturn(new ByteArrayOutputStream()).anyTimes();
EasyMock.replay(pty);
try (PosixSysTerminal terminal = new PosixSysTerminal(
"name", "ansi", pty,
Charset.defaultCharset().name(), true,
SignalHandler.SIG_DFL)) {
assertEquals(0, terminal.nativeHandlers.size());
SignalHandler prev = terminal.handle(Signal.INT, s -> {});
assertEquals(1, terminal.nativeHandlers.size());
terminal.handle(Signal.INT, prev);
assertEquals(0, terminal.nativeHandlers.size());
}
}
}

0 comments on commit 65d06a0

Please sign in to comment.