diff --git a/src/main/java/net/logstash/logback/appender/AsyncDisruptorAppender.java b/src/main/java/net/logstash/logback/appender/AsyncDisruptorAppender.java index bef2d01c..abeb8cca 100644 --- a/src/main/java/net/logstash/logback/appender/AsyncDisruptorAppender.java +++ b/src/main/java/net/logstash/logback/appender/AsyncDisruptorAppender.java @@ -100,6 +100,10 @@ * @param type of event ({@link ILoggingEvent} or {@link IAccessEvent}). */ public abstract class AsyncDisruptorAppender> extends UnsynchronizedAppenderBase { + /** + * Time in nanos to wait between drain attempts during the shutdown phase + */ + private static final long SLEEP_TIME_DURING_SHUTDOWN = 50 * 1_000_000L; // 50ms protected static final String APPENDER_NAME_FORMAT = "%1$s"; protected static final String THREAD_INDEX_FORMAT = "%2$d"; @@ -469,34 +473,40 @@ public void stop() { /* - * Shutdown disruptor and executorService + * Shutdown Disruptor + * + * Calling Disruptor#shutdown() will wait until all enqueued events are fully processed, + * but this waiting happens in a busy-spin. To avoid wasting CPU we wait for at most the configured + * grace period before asking the Disruptor for an immediate shutdown. */ - boolean errorDuringShutdown = false; - long remainingTime = Math.max(0, getShutdownGracePeriod().getMilliseconds()); - long startTime = System.currentTimeMillis(); + long deadline = getShutdownGracePeriod().getMilliseconds() < 0 ? Long.MAX_VALUE : System.currentTimeMillis() + getShutdownGracePeriod().getMilliseconds(); + while( !isRingBufferEmpty() && (System.currentTimeMillis()