From fa25c002e535a8efbf93757277c534dff3a358b7 Mon Sep 17 00:00:00 2001 From: Jonathan Cobb Date: Wed, 26 Aug 2020 10:02:16 -0400 Subject: [PATCH] safer monitoring and cleanup --- .../util/io/multi/MultiUnderflowHandler.java | 28 +++++++++++++++---- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/cobbzilla/util/io/multi/MultiUnderflowHandler.java b/src/main/java/org/cobbzilla/util/io/multi/MultiUnderflowHandler.java index ee02c26..133d799 100644 --- a/src/main/java/org/cobbzilla/util/io/multi/MultiUnderflowHandler.java +++ b/src/main/java/org/cobbzilla/util/io/multi/MultiUnderflowHandler.java @@ -11,6 +11,7 @@ import java.io.IOException; import java.util.Iterator; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicBoolean; import static java.util.UUID.randomUUID; import static java.util.concurrent.TimeUnit.SECONDS; @@ -29,11 +30,20 @@ public class MultiUnderflowHandler extends SimpleDaemon { @Override protected long getSleepTime() { return checkInterval; } @Override protected void process() { + if (log.isTraceEnabled()) log.trace("process: examining "+handlers.size()+" underflow handlers"); for (Iterator iter = handlers.values().iterator(); iter.hasNext(); ) { final MultiUnderflowHandler underflow = iter.next(); - if (now() - underflow.getLastRead() > underflow.getUnderflowTimeout()) { - log.error("process: underflow timed out, terminating: name="+underflow.getHandlerName()+" thread="+underflow.getThread()); + if (underflow.closed()) { + if (log.isDebugEnabled()) log.debug("process: removing closed handler: name="+underflow.getHandlerName()+" thread="+underflow.getThread()); iter.remove(); + + } else if (underflow.getLastRead() > 0 && !underflow.getThread().isAlive()) { + if (log.isDebugEnabled()) log.debug("process: removing dead thread: name="+underflow.getHandlerName()+" thread="+underflow.getThread()); + iter.remove(); + + } else if (now() - underflow.getLastRead() > underflow.getUnderflowTimeout()) { + iter.remove(); + if (log.isErrorEnabled()) log.error("process: underflow timed out, terminating: name="+underflow.getHandlerName()+" thread="+underflow.getThread()); terminate(underflow.getThread(), TERMINATE_TIMEOUT); } } @@ -48,15 +58,18 @@ public class MultiUnderflowHandler extends SimpleDaemon { @Getter @Setter private long maxUnderflowSleep = 500; - @Getter @Setter private long lastRead = now(); + @Getter @Setter private long lastRead = 0; @Getter @Setter private long firstUnderflow = 0; @Getter @Setter private long underflowTimeout = SECONDS.toMillis(60); private long underflowSleep = minUnderflowSleep; @Getter private Thread thread; + private final AtomicBoolean closed = new AtomicBoolean(false); + public boolean closed () { return closed.get(); } public void handleUnderflow() throws IOException { if (thread == null) { thread = Thread.currentThread(); + lastRead = now(); handlers.put(id, this); } if (firstUnderflow == 0) { @@ -73,16 +86,21 @@ public class MultiUnderflowHandler extends SimpleDaemon { } public void handleSuccessfulRead() { + lastRead = now(); if (thread == null) { thread = Thread.currentThread(); handlers.put(id, this); } firstUnderflow = 0; - lastRead = now(); underflowSleep = minUnderflowSleep; } public void close() { - + if (!closed()) { + closed.set(true); + if (log.isDebugEnabled()) log.debug(handlerName + ": closing"); + handlers.remove(id); + } } + }