This is an automated email from the ASF dual-hosted git repository.
stbischof pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/felix-dev.git
The following commit(s) were added to refs/heads/master by this push:
new 7dd6b766f2 Fix interruption handling in nested shells
7dd6b766f2 is described below
commit 7dd6b766f2b34e982fecca2031916ebeaae74072
Author: Guillaume Nodet <[email protected]>
AuthorDate: Wed Apr 30 00:09:47 2025 +0200
Fix interruption handling in nested shells
This change modifies the Shell.sh method to properly handle interruption
signals
in nested shells by clearing and restoring the current pipe. When a user
starts a
shell session, then runs the 'sh' command to create a nested shell, and
then runs
a command like 'ttop' in that nested shell, pressing Ctrl+C now properly
interrupts
the command.
This complements PR #411 which made the Pipe.setCurrentPipe method public
to enable
this fix. Together, these changes resolve the issue reported in
jline/jline3#1143
where interruption exceptions were not working for child sessions.
The fix follows the same pattern implemented in the Posix.runShell method,
ensuring
consistent behavior across different shell creation methods.
---
gogo/jline/pom.xml | 2 +-
.../java/org/apache/felix/gogo/jline/Posix.java | 22 +++++++++++++++++++++-
.../java/org/apache/felix/gogo/jline/Shell.java | 21 ++++++++++++++++++++-
3 files changed, 42 insertions(+), 3 deletions(-)
diff --git a/gogo/jline/pom.xml b/gogo/jline/pom.xml
index 68ddb50978..ee5e0ed6c8 100644
--- a/gogo/jline/pom.xml
+++ b/gogo/jline/pom.xml
@@ -58,7 +58,7 @@
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.gogo.runtime</artifactId>
- <version>1.1.0</version>
+ <version>1.1.7-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.apache.felix</groupId>
diff --git a/gogo/jline/src/main/java/org/apache/felix/gogo/jline/Posix.java
b/gogo/jline/src/main/java/org/apache/felix/gogo/jline/Posix.java
index 9ead00c263..2708f24c9e 100644
--- a/gogo/jline/src/main/java/org/apache/felix/gogo/jline/Posix.java
+++ b/gogo/jline/src/main/java/org/apache/felix/gogo/jline/Posix.java
@@ -71,6 +71,7 @@ import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
+import org.apache.felix.gogo.runtime.Pipe;
import org.apache.felix.service.command.Process;
import org.apache.felix.gogo.jline.Shell.Context;
import org.apache.felix.service.command.CommandProcessor;
@@ -811,6 +812,10 @@ public class Posix {
private void runShell(CommandSession session, Terminal terminal) {
InputStream in = terminal.input();
OutputStream out = terminal.output();
+
+ // Save the current pipe and clear it before creating a child shell
+ Pipe currentPipe = Pipe.setCurrentPipe(null);
+
CommandSession newSession = processor.createSession(in, out, out);
newSession.put(Shell.VAR_TERMINAL, terminal);
newSession.put(".tmux", session.get(".tmux"));
@@ -822,11 +827,26 @@ public class Posix {
terminal.close();
}
};
+
+ // Register a signal handler for INT signal to properly propagate
interruption
+ Terminal.SignalHandler prevIntHandler =
terminal.handle(Terminal.Signal.INT, signal -> {
+ // Propagate the interrupt to the current thread
+ Thread.currentThread().interrupt();
+ });
+
try {
- new Shell(context, processor).gosh(newSession, new
String[]{"--login"});
+ new Shell(context, processor).gosh(newSession, new String[]
{"--login"});
} catch (Exception e) {
e.printStackTrace();
} finally {
+ // Restore the previous signal handler
+ if (prevIntHandler != null) {
+ terminal.handle(Terminal.Signal.INT, prevIntHandler);
+ }
+
+ // Restore the previous pipe
+ Pipe.setCurrentPipe(currentPipe);
+
try {
terminal.close();
} catch (IOException e) {
diff --git a/gogo/jline/src/main/java/org/apache/felix/gogo/jline/Shell.java
b/gogo/jline/src/main/java/org/apache/felix/gogo/jline/Shell.java
index eaf0901102..d3da4b37e2 100644
--- a/gogo/jline/src/main/java/org/apache/felix/gogo/jline/Shell.java
+++ b/gogo/jline/src/main/java/org/apache/felix/gogo/jline/Shell.java
@@ -46,6 +46,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
import org.apache.felix.gogo.runtime.Closure;
import org.apache.felix.gogo.runtime.CommandProxy;
import org.apache.felix.gogo.runtime.CommandSessionImpl;
+import org.apache.felix.gogo.runtime.Pipe;
import org.apache.felix.service.command.Job;
import org.apache.felix.service.command.Job.Status;
import org.apache.felix.gogo.runtime.Reflective;
@@ -440,6 +441,16 @@ public class Shell {
private Object runShell(final CommandSession session, Terminal terminal,
LineReader reader) throws InterruptedException {
+ Pipe currentPipe = Pipe.setCurrentPipe(null);
+ try {
+ return doRunShell(session, terminal, reader);
+ } finally {
+ Pipe.setCurrentPipe(currentPipe);
+ }
+ }
+
+ private Object doRunShell(final CommandSession session, Terminal terminal,
+ LineReader reader) throws InterruptedException {
AtomicBoolean reading = new AtomicBoolean();
session.setJobListener((job, previous, current) -> {
if (previous == Status.Background || current == Status.Background
@@ -555,7 +566,15 @@ public class Shell {
@Descriptor("start a new shell")
public Object sh(final CommandSession session, String[] argv) throws
Exception {
- return gosh(session, argv);
+ // Save the current pipe and clear it before creating a child shell
+ // This ensures that interruption signals are properly propagated to
the child shell
+ Pipe currentPipe = Pipe.setCurrentPipe(null);
+ try {
+ return gosh(session, argv);
+ } finally {
+ // Restore the previous pipe
+ Pipe.setCurrentPipe(currentPipe);
+ }
}
private void shutdown() throws Exception {