diff --git a/bubble-server/src/main/java/bubble/service/stream/ActiveStreamState.java b/bubble-server/src/main/java/bubble/service/stream/ActiveStreamState.java index 7fd69214..63170af3 100644 --- a/bubble-server/src/main/java/bubble/service/stream/ActiveStreamState.java +++ b/bubble-server/src/main/java/bubble/service/stream/ActiveStreamState.java @@ -14,6 +14,7 @@ import org.cobbzilla.util.http.HttpContentEncodingType; import org.cobbzilla.util.io.FilterInputStreamViaOutputStream; import org.cobbzilla.util.io.FixedByteArrayInputStream; import org.cobbzilla.util.io.multi.MultiStream; +import org.cobbzilla.util.io.multi.MultiUnderflowHandlerMonitor; import org.cobbzilla.util.system.Bytes; import java.io.ByteArrayInputStream; @@ -39,6 +40,22 @@ class ActiveStreamState { // this avoids errors when creating a GZIPInputStream when only one or a few bytes are available public static final long MIN_BYTES_BEFORE_WRAP = Bytes.KB; + static { + // do not terminate threads that are idling just fine + // only terminate threads with abnormally long or short stacks + MultiUnderflowHandlerMonitor.DEFAULT_UNDERFLOW_MONITOR.setTerminateThreadFunc(t -> { + final StackTraceElement[] stack = t.getStackTrace(); + if (stack.length < 5) return false; + if (stack.length > 15) return true; + for (int i=0; i<5; i++) { + if (stack[i].toString().contains("org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run")) { + return false; + } + } + return true; + }); + } + private final FilterHttpRequest request; private final String requestId; private final AppRuleHarness firstRule; diff --git a/utils/cobbzilla-utils b/utils/cobbzilla-utils index 51654454..9481a2c0 160000 --- a/utils/cobbzilla-utils +++ b/utils/cobbzilla-utils @@ -1 +1 @@ -Subproject commit 5165445487522986bb7c112e2b41a3563c6b9b69 +Subproject commit 9481a2c0a68e50d6ad3b984b77f41ce0a57de963