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 {

Reply via email to