From 7f0ac302f79ede92b090484f260c7dc54a8fb937 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?JB=20Onofr=C3=A9?= Date: Fri, 13 Mar 2026 19:14:29 +0100 Subject: [PATCH] fix(shell): prevent LinkageError from killing the local console thread When the JLine bundle is refreshed during runtime (e.g., due to feature install/update), the bundle classloader changes and AttributedString may be loaded by two different classloaders. This causes a LinkageError in ShellUtil.applyStyle(). The logException() error handler only caught Exception, not Error, so the LinkageError escaped and killed the console thread. Broaden the catch to Throwable so classloading errors during exception display are handled gracefully. Also set command to empty string in readCommand()'s catch-all handler so transient errors re-prompt instead of exiting the session. --- .../apache/karaf/shell/impl/console/ConsoleSessionImpl.java | 1 + .../main/java/org/apache/karaf/shell/support/ShellUtil.java | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/ConsoleSessionImpl.java b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/ConsoleSessionImpl.java index a14ee421778..61a6aaec0c3 100644 --- a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/ConsoleSessionImpl.java +++ b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/ConsoleSessionImpl.java @@ -473,6 +473,7 @@ private CharSequence readCommand(AtomicBoolean reading) throws UserInterruptExce command = ""; } catch (Throwable t) { ShellUtil.logException(this, t); + command = ""; } finally { reading.set(false); } diff --git a/shell/core/src/main/java/org/apache/karaf/shell/support/ShellUtil.java b/shell/core/src/main/java/org/apache/karaf/shell/support/ShellUtil.java index de871baf02f..862a895c8e4 100644 --- a/shell/core/src/main/java/org/apache/karaf/shell/support/ShellUtil.java +++ b/shell/core/src/main/java/org/apache/karaf/shell/support/ShellUtil.java @@ -183,8 +183,9 @@ public static void logException(Session session, Throwable t) { session.getConsole().println(str); } session.getConsole().flush(); - } catch (Exception ignore) { - // ignore + } catch (Throwable ignore) { + // ignore (catch Throwable to handle LinkageError from JLine classloader + // changes during bundle refresh, which would otherwise kill the console thread) } }