diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/microbot/Microbot.java b/runelite-client/src/main/java/net/runelite/client/plugins/microbot/Microbot.java index 840cd92abd..67675b83c5 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/microbot/Microbot.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/microbot/Microbot.java @@ -464,6 +464,9 @@ public static void showMessage(String message) { } else { SwingUtilities.invokeAndWait(messageRunnable); } + } catch (InterruptedException ex) { + Thread.currentThread().interrupt(); + log.debug("Interrupted while displaying message {}", message); } catch (Exception ex) { log.error("Error displaying message {}:", message, ex); } @@ -487,6 +490,9 @@ public static void showMessage(String message, int disposeTime) { } else { SwingUtilities.invokeAndWait(messageRunnable); } + } catch (InterruptedException ex) { + Thread.currentThread().interrupt(); + log.debug("Interrupted while displaying message {}", message); } catch (Exception ex) { log.error("Error displaying message {}:", message, ex); } @@ -714,7 +720,9 @@ public static void log(String message, Level level, Exception ex) { log.warn(message); break; case ERROR: - if (ex != null) { + if (isInterruption(ex)) { + log.debug(message, ex); + } else if (ex != null) { log.error(message, ex); } else { log.error(message); @@ -729,6 +737,16 @@ public static void log(String message, Level level, Exception ex) { } } + static boolean isInterruption(Throwable ex) { + Throwable t = ex; + for (int depth = 0; t != null && depth < 64; depth++, t = t.getCause() == t ? null : t.getCause()) { + if (t instanceof InterruptedException) { + return true; + } + } + return false; + } + /** * Opens a pop‑up interface with the specified title and description. *

diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/microbot/diagnostics/ScriptErrorReporter.java b/runelite-client/src/main/java/net/runelite/client/plugins/microbot/diagnostics/ScriptErrorReporter.java index d9a37b78c2..b328274e18 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/microbot/diagnostics/ScriptErrorReporter.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/microbot/diagnostics/ScriptErrorReporter.java @@ -89,6 +89,10 @@ protected void append(ILoggingEvent event) } IThrowableProxy root = rootCause(event.getThrowableProxy()); + if (root != null && InterruptedException.class.getName().equals(root.getClassName())) + { + return; + } List frames = frames(root); String fingerprint = root == null ? event.getLoggerName() + "|" + scrub(event.getMessage()).replaceAll("\\d+", "#") diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/microbot/MicrobotLogInterruptTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/microbot/MicrobotLogInterruptTest.java new file mode 100644 index 0000000000..a6d7c47f13 --- /dev/null +++ b/runelite-client/src/test/java/net/runelite/client/plugins/microbot/MicrobotLogInterruptTest.java @@ -0,0 +1,65 @@ +package net.runelite.client.plugins.microbot; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.read.ListAppender; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.slf4j.LoggerFactory; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; + +public class MicrobotLogInterruptTest +{ + private Logger logger; + private ListAppender appender; + private Level previousLevel; + + @Before + public void setUp() + { + logger = (Logger) LoggerFactory.getLogger(Microbot.class); + previousLevel = logger.getLevel(); + logger.setLevel(Level.DEBUG); + appender = new ListAppender<>(); + appender.start(); + logger.addAppender(appender); + } + + @After + public void tearDown() + { + logger.detachAppender(appender); + logger.setLevel(previousLevel); + } + + @Test + public void interruptedClientThreadWaitIsNotLoggedAsError() + { + Microbot.logStackTrace("AttackNpcScript", new RuntimeException("Interrupted waiting for client thread", new InterruptedException())); + + assertEquals(1, appender.list.size()); + assertEquals(Level.DEBUG, appender.list.get(0).getLevel()); + } + + @Test + public void otherFailuresStillLogError() + { + Microbot.logStackTrace("AttackNpcScript", new IllegalStateException("boom")); + + assertEquals(1, appender.list.size()); + assertEquals(Level.ERROR, appender.list.get(0).getLevel()); + } + + @Test + public void cyclicCauseChainTerminates() + { + IllegalStateException a = new IllegalStateException("a"); + IllegalStateException b = new IllegalStateException("b", a); + a.initCause(b); + + assertFalse(Microbot.isInterruption(a)); + } +} diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/microbot/diagnostics/ScriptErrorReporterTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/microbot/diagnostics/ScriptErrorReporterTest.java index f524a8d64b..4b3cf86854 100644 --- a/runelite-client/src/test/java/net/runelite/client/plugins/microbot/diagnostics/ScriptErrorReporterTest.java +++ b/runelite-client/src/test/java/net/runelite/client/plugins/microbot/diagnostics/ScriptErrorReporterTest.java @@ -193,6 +193,14 @@ public void requeuesRejectedBatch() assertEquals(2, captor.getValue().getAsJsonArray("errors").get(0).getAsJsonObject().get("count").getAsInt()); } + @Test + public void ignoresInterruptedWaits() + { + log(Level.ERROR, "AttackNpcScript", new RuntimeException("Interrupted waiting for client thread", new InterruptedException())); + log(Level.ERROR, "Error displaying message {}:", new InterruptedException()); + assertEquals(0, reporter.pendingCount()); + } + @Test public void requeuesBatchWhenSubmitThrows() {