LOG4J2-3102: AsyncAppender background thread is a daemon
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/AsyncAppenderEventDispatcher.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/AsyncAppenderEventDispatcher.java
index a01f68d..d9efc94 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/AsyncAppenderEventDispatcher.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/AsyncAppenderEventDispatcher.java
@@ -50,6 +50,7 @@
             final List<AppenderControl> appenders,
             final BlockingQueue<LogEvent> queue) {
         super("AsyncAppenderEventDispatcher-" + THREAD_COUNTER.incrementAndGet() + "-" + name);
+        this.setDaemon(true);
         this.errorAppender = errorAppender;
         this.appenders = appenders;
         this.queue = queue;
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/AsyncAppenderTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/AsyncAppenderTest.java
index fad0cb7..68abb56 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/AsyncAppenderTest.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/AsyncAppenderTest.java
@@ -29,6 +29,7 @@
 
 import java.util.List;
 import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
 
 import static org.junit.jupiter.api.Assertions.*;
 
@@ -74,6 +75,14 @@
     void defaultAsyncAppenderConfig(final LoggerContext context) throws InterruptedException {
         rewriteTest(context);
         exceptionTest(context);
+
+        List<Thread> backgroundThreads = Thread.getAllStackTraces().keySet().stream()
+                .filter(AsyncAppenderEventDispatcher.class::isInstance)
+                .collect(Collectors.toList());
+        assertFalse(backgroundThreads.isEmpty(), "Failed to locate background thread");
+        for (Thread thread : backgroundThreads) {
+            assertTrue(thread.isDaemon(), "AsyncAppender should use daemon threads");
+        }
     }
 
     @Test
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 077fbd2..f7cc337 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -208,6 +208,10 @@
         Allow a PatternSelector to be specified on GelfLayout.
       </action>
       <!-- FIXES -->
+      <action issue="LOG4J2-3102" dev="ckozak" type="fix">
+        Fix a regression in 2.14.1 which allowed the AsyncAppender background thread to keep the JVM alive because
+        the daemon flag was not set.
+      </action>
       <action issue="LOG4J2-3103" dev="ckozak" type="fix" due-to="Mike Glazer">
         Fix race condition which can result in ConcurrentModificationException on context.stop.
       </action>