Clean up access logging threads when Undertow is stopped

Closes gh-12742
This commit is contained in:
Phillip Webb 2015-12-16 23:24:22 +00:00 committed by Andy Wilkinson
parent e7b03f7ca3
commit 2bb7a430cf
2 changed files with 63 additions and 17 deletions

View File

@ -32,6 +32,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.EventListener;
import java.util.List;
import java.util.Locale;
import java.util.Map;
@ -46,6 +47,8 @@ import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509ExtendedKeyManager;
import javax.servlet.ServletContainerInitializer;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.ServletException;
import io.undertow.Undertow;
@ -64,6 +67,7 @@ import io.undertow.server.session.SessionManager;
import io.undertow.servlet.Servlets;
import io.undertow.servlet.api.DeploymentInfo;
import io.undertow.servlet.api.DeploymentManager;
import io.undertow.servlet.api.ListenerInfo;
import io.undertow.servlet.api.MimeMapping;
import io.undertow.servlet.api.ServletContainerInitializerInfo;
import io.undertow.servlet.api.ServletStackTraces;
@ -417,34 +421,41 @@ public class UndertowEmbeddedServletContainerFactory
}
private void configureAccessLog(DeploymentInfo deploymentInfo) {
deploymentInfo.addInitialHandlerChainWrapper(new HandlerWrapper() {
@Override
public HttpHandler wrap(HttpHandler handler) {
return createAccessLogHandler(handler);
}
});
}
private AccessLogHandler createAccessLogHandler(HttpHandler handler) {
try {
createAccessLogDirectoryIfNecessary();
XnioWorker worker = createWorker();
String prefix = (this.accessLogPrefix != null ? this.accessLogPrefix
: "access_log.");
AccessLogReceiver accessLogReceiver = new DefaultAccessLogReceiver(
createWorker(), this.accessLogDirectory, prefix, this.accessLogSuffix,
DefaultAccessLogReceiver accessLogReceiver = new DefaultAccessLogReceiver(
worker, this.accessLogDirectory, prefix, this.accessLogSuffix,
this.accessLogRotate);
String formatString = (this.accessLogPattern != null ? this.accessLogPattern
: "common");
return new AccessLogHandler(handler, accessLogReceiver, formatString,
Undertow.class.getClassLoader());
EventListener listener = new AccessLogShutdownListener(worker,
accessLogReceiver);
deploymentInfo.addListener(new ListenerInfo(AccessLogShutdownListener.class,
new ImmediateInstanceFactory<EventListener>(listener)));
deploymentInfo.addInitialHandlerChainWrapper(new HandlerWrapper() {
@Override
public HttpHandler wrap(HttpHandler handler) {
return createAccessLogHandler(handler, accessLogReceiver);
}
});
}
catch (IOException ex) {
throw new IllegalStateException("Failed to create AccessLogHandler", ex);
}
}
private AccessLogHandler createAccessLogHandler(HttpHandler handler,
AccessLogReceiver accessLogReceiver) {
createAccessLogDirectoryIfNecessary();
String formatString = (this.accessLogPattern != null) ? this.accessLogPattern
: "common";
return new AccessLogHandler(handler, accessLogReceiver, formatString,
Undertow.class.getClassLoader());
}
private void createAccessLogDirectoryIfNecessary() {
Assert.state(this.accessLogDirectory != null, "Access log directory is not set");
if (!this.accessLogDirectory.isDirectory() && !this.accessLogDirectory.mkdirs()) {
@ -790,4 +801,33 @@ public class UndertowEmbeddedServletContainerFactory
}
private static class AccessLogShutdownListener implements ServletContextListener {
private final XnioWorker worker;
private final DefaultAccessLogReceiver accessLogReceiver;
AccessLogShutdownListener(XnioWorker worker,
DefaultAccessLogReceiver accessLogReceiver) {
this.worker = worker;
this.accessLogReceiver = accessLogReceiver;
}
@Override
public void contextInitialized(ServletContextEvent sce) {
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
try {
this.accessLogReceiver.close();
this.worker.shutdown();
}
catch (IOException ex) {
throw new IllegalStateException(ex);
}
}
}
}

View File

@ -37,6 +37,7 @@ import io.undertow.servlet.api.DeploymentInfo;
import io.undertow.servlet.api.DeploymentManager;
import io.undertow.servlet.api.ServletContainer;
import org.apache.jasper.servlet.JspServlet;
import org.junit.AfterClass;
import org.junit.Test;
import org.mockito.InOrder;
@ -73,6 +74,11 @@ public class UndertowEmbeddedServletContainerFactoryTests
return new UndertowEmbeddedServletContainerFactory(0);
}
@AfterClass
public static void afterClass() {
}
@Test
public void errorPage404() throws Exception {
AbstractEmbeddedServletContainerFactory factory = getFactory();