I didn't want to manage a pool but to do a fire and forget. As for multiple recon figurations, I don't know of the top of my head. I don't want to introduce locking here but I will see if that is a problem.
Sent from my iPad > On May 19, 2014, at 4:15 AM, Gary Gregory <[email protected]> wrote: > > Does this guarantee that only one concurrent reconfiguration happens at one > any one time? Should it? Use a size 1 thread pool executor with a queue? > > Gary > > > -------- Original message -------- > From: [email protected] > Date:05/19/2014 00:53 (GMT-05:00) > To: [email protected] > Subject: svn commit: r1595741 - in /logging/log4j/log4j2/trunk: > log4j-core/src/main/java/org/apache/logging/log4j/core/config/ > log4j-core/src/test/java/org/apache/logging/log4j/core/ > log4j-core/src/test/java/org/apache/logging/log4j/core/config/ > log4j-core/src/... > > Author: rgoers > Date: Mon May 19 04:53:11 2014 > New Revision: 1595741 > > URL: http://svn.apache.org/r1595741 > Log: > LOG4J2-620 - Perform reconfiguration in a separate thread to prevent > deadlocks. > > Added: > > logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/config/ReconfigurationDeadlockTest.java > > logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/test/SomethingThatUsesLogging.java > > logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/test/appender/UsesLoggingAppender.java > > logging/log4j/log4j2/trunk/log4j-core/src/test/resources/reconfiguration-deadlock.xml > Modified: > > logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/config/FileConfigurationMonitor.java > > logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/FileConfigTest.java > > logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/LoggerTest.java > > logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/config/TestConfigurator.java > logging/log4j/log4j2/trunk/src/changes/changes.xml > > Modified: > logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/config/FileConfigurationMonitor.java > URL: > http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/config/FileConfigurationMonitor.java?rev=1595741&r1=1595740&r2=1595741&view=diff > ============================================================================== > --- > logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/config/FileConfigurationMonitor.java > (original) > +++ > logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/config/FileConfigurationMonitor.java > Mon May 19 04:53:11 2014 > @@ -81,7 +81,9 @@ public class FileConfigurationMonitor im > if (file.lastModified() > lastModified) { > lastModified = file.lastModified(); > for (final ConfigurationListener listener : listeners) { > - listener.onChange(reconfigurable); > + Thread thread = new Thread(new > ReconfigurationWorker(listener, reconfigurable)); > + thread.setDaemon(true); > + thread.start(); > } > } > } finally { > @@ -89,4 +91,20 @@ public class FileConfigurationMonitor im > } > } > } > + > + private class ReconfigurationWorker implements Runnable { > + > + private final ConfigurationListener listener; > + private final Reconfigurable reconfigurable; > + > + public ReconfigurationWorker(ConfigurationListener listener, > Reconfigurable reconfigurable) { > + this.listener = listener; > + this.reconfigurable = reconfigurable; > + } > + > + @Override > + public void run() { > + listener.onChange(reconfigurable); > + } > + } > } > > Modified: > logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/FileConfigTest.java > URL: > http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/FileConfigTest.java?rev=1595741&r1=1595740&r2=1595741&view=diff > ============================================================================== > --- > logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/FileConfigTest.java > (original) > +++ > logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/FileConfigTest.java > Mon May 19 04:53:11 2014 > @@ -81,6 +81,7 @@ public class FileConfigTest { > for (int i = 0; i < 17; ++i) { > logger.debug("Reconfigure"); > } > + Thread.sleep(100); > final Configuration cfg = ctx.getConfiguration(); > assertNotNull("No configuration", cfg); > assertTrue("Reconfiguration failed", cfg != config); > > Modified: > logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/LoggerTest.java > URL: > http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/LoggerTest.java?rev=1595741&r1=1595740&r2=1595741&view=diff > ============================================================================== > --- > logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/LoggerTest.java > (original) > +++ > logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/LoggerTest.java > Mon May 19 04:53:11 2014 > @@ -238,6 +238,7 @@ public class LoggerTest { > for (int i = 0; i < 17; ++i) { > logger.debug("Reconfigure"); > } > + Thread.sleep(100); > final Configuration cfg = ctx.getConfiguration(); > assertNotNull("No configuration", cfg); > assertTrue("Reconfiguration failed", cfg != config); > > Added: > logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/config/ReconfigurationDeadlockTest.java > URL: > http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/config/ReconfigurationDeadlockTest.java?rev=1595741&view=auto > ============================================================================== > --- > logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/config/ReconfigurationDeadlockTest.java > (added) > +++ > logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/config/ReconfigurationDeadlockTest.java > Mon May 19 04:53:11 2014 > @@ -0,0 +1,127 @@ > +/* > + * Licensed to the Apache Software Foundation (ASF) under one or more > + * contributor license agreements. See the NOTICE file distributed with > + * this work for additional information regarding copyright ownership. > + * The ASF licenses this file to You under the Apache license, Version 2.0 > + * (the "License"); you may not use this file except in compliance with > + * the License. You may obtain a copy of the License at > + * > + * http://www.apache.org/licenses/LICENSE-2.0 > + * > + * Unless required by applicable law or agreed to in writing, software > + * distributed under the License is distributed on an "AS IS" BASIS, > + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. > + * See the license for the specific language governing permissions and > + * limitations under the license. > + */ > +package org.apache.logging.log4j.core.config; > + > +import org.apache.logging.log4j.LogManager; > +import org.apache.logging.log4j.Logger; > +import org.apache.logging.log4j.junit.InitialLoggerContext; > +import org.apache.logging.log4j.message.ThreadDumpMessage; > +import org.junit.Rule; > +import org.junit.Test; > + > +import java.io.File; > + > +import static org.junit.Assert.assertTrue; > + > +/** > + * > + */ > +public class ReconfigurationDeadlockTest { > + > + @Rule > + public InitialLoggerContext init = new > InitialLoggerContext("reconfiguration-deadlock.xml"); > + private static final int THREAD_COUNT = 5; > + private static final boolean[] finished = new boolean[THREAD_COUNT]; > + private static LoggerThread[] threads = new LoggerThread[THREAD_COUNT]; > + > + @Test > + public void testReconfig() throws InterruptedException { > + > + Updater updater = new Updater(); > + for (int i = 0; i < THREAD_COUNT; ++i) { > + threads[i] = new LoggerThread(i); > + threads[i].setDaemon(true); > + } > + for (int i = 0; i < THREAD_COUNT; ++i) { > + > + threads[i].start(); > + } > + updater.setDaemon(true); > + updater.start(); > + Thread.sleep(100); > + boolean stillWaiting = true; > + for (int i = 0; i < 200; ++i) { > + int index = 0; > + for (; index < THREAD_COUNT; ++index) { > + if (!finished[index]) { > + break; > + } > + } > + if (index == THREAD_COUNT) { > + stillWaiting = false; > + break; > + } > + Thread.sleep(100); > + } > + updater.shutdown = true; > + if (stillWaiting) { > + ThreadDumpMessage message = new ThreadDumpMessage("Waiting"); > + System.err.print(message.getFormattedMessage()); > + } > + for (int i = 0; i < THREAD_COUNT; ++i) { > + if (threads[i].isAlive()) { > + threads[i].interrupt(); > + } > + } > + assertTrue("loggerThread didn't finish", stillWaiting == false); > + > + } > + > + private class LoggerThread extends Thread { > + > + private final Logger logger = LogManager.getRootLogger(); > + private final int index; > + > + public LoggerThread(int i) { > + index = i; > + } > + @Override > + public void run() { > + int i = 0; > + try { > + for (i=0; i < 30; ++i) { > + logger.error("Thread: " + index + ", Test: " + i++); > + } > + } catch (Exception ie) { > + return; > + } > + finished[index] = true; > + } > + } > + > + private class Updater extends Thread { > + > + public volatile boolean shutdown = false; > + > + @Override > + public void run() { > + while (!shutdown) { > + try { > + Thread.sleep(1000); > + } catch (InterruptedException e) { > + e.printStackTrace(); > + } > + // for running from IDE > + File file = new > File("target/test-classes/reconfiguration-deadlock.xml"); > + if (file.exists()) { > + file.setLastModified(System.currentTimeMillis()); > + } > + } > + } > + } > + > +} > > Modified: > logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/config/TestConfigurator.java > URL: > http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/config/TestConfigurator.java?rev=1595741&r1=1595740&r2=1595741&view=diff > ============================================================================== > --- > logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/config/TestConfigurator.java > (original) > +++ > logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/config/TestConfigurator.java > Mon May 19 04:53:11 2014 > @@ -235,6 +235,7 @@ public class TestConfigurator { > for (int i = 0; i < 17; ++i) { > logger.debug("Test message " + i); > } > + Thread.sleep(100); > final Configuration newConfig = ctx.getConfiguration(); > assertTrue("Configuration not reset", newConfig != config); > Configurator.shutdown(ctx); > > Added: > logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/test/SomethingThatUsesLogging.java > URL: > http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/test/SomethingThatUsesLogging.java?rev=1595741&view=auto > ============================================================================== > --- > logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/test/SomethingThatUsesLogging.java > (added) > +++ > logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/test/SomethingThatUsesLogging.java > Mon May 19 04:53:11 2014 > @@ -0,0 +1,36 @@ > +/* > + * Licensed to the Apache Software Foundation (ASF) under one or more > + * contributor license agreements. See the NOTICE file distributed with > + * this work for additional information regarding copyright ownership. > + * The ASF licenses this file to You under the Apache license, Version 2.0 > + * (the "License"); you may not use this file except in compliance with > + * the License. You may obtain a copy of the License at > + * > + * http://www.apache.org/licenses/LICENSE-2.0 > + * > + * Unless required by applicable law or agreed to in writing, software > + * distributed under the License is distributed on an "AS IS" BASIS, > + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. > + * See the license for the specific language governing permissions and > + * limitations under the license. > + */ > +package org.apache.logging.log4j.test; > + > +import org.apache.logging.log4j.Level; > +import org.apache.logging.log4j.LogManager; > +import org.apache.logging.log4j.Logger; > +/** > + * > + */ > +public class SomethingThatUsesLogging { > + > + private Logger logger; > + > + public SomethingThatUsesLogging() { > + logger = LogManager.getLogger(); > + } > + > + public void doSomething() { > + logger.isEnabled(Level.DEBUG); > + } > +} > > Added: > logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/test/appender/UsesLoggingAppender.java > URL: > http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/test/appender/UsesLoggingAppender.java?rev=1595741&view=auto > ============================================================================== > --- > logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/test/appender/UsesLoggingAppender.java > (added) > +++ > logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/test/appender/UsesLoggingAppender.java > Mon May 19 04:53:11 2014 > @@ -0,0 +1,69 @@ > +/* > + * Licensed to the Apache Software Foundation (ASF) under one or more > + * contributor license agreements. See the NOTICE file distributed with > + * this work for additional information regarding copyright ownership. > + * The ASF licenses this file to You under the Apache license, Version 2.0 > + * (the "License"); you may not use this file except in compliance with > + * the License. You may obtain a copy of the License at > + * > + * http://www.apache.org/licenses/LICENSE-2.0 > + * > + * Unless required by applicable law or agreed to in writing, software > + * distributed under the License is distributed on an "AS IS" BASIS, > + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. > + * See the license for the specific language governing permissions and > + * limitations under the license. > + */ > +package org.apache.logging.log4j.test.appender; > + > +import org.apache.logging.log4j.core.Filter; > +import org.apache.logging.log4j.core.Layout; > +import org.apache.logging.log4j.core.LogEvent; > +import org.apache.logging.log4j.core.appender.AbstractAppender; > +import org.apache.logging.log4j.core.config.plugins.Plugin; > +import org.apache.logging.log4j.core.config.plugins.PluginAttribute; > +import org.apache.logging.log4j.core.config.plugins.PluginElement; > +import org.apache.logging.log4j.core.config.plugins.PluginFactory; > +import org.apache.logging.log4j.test.SomethingThatUsesLogging; > + > +/** > + * > + */ > +@Plugin(name = "UsesLoggingAppender", category = "Core", elementType = > "appender", printObject = true) > +public final class UsesLoggingAppender extends AbstractAppender { > + > + private SomethingThatUsesLogging thing; > + > + private UsesLoggingAppender(String name, Filter filter, Layout<?> > layout, boolean ignoreExceptions) { > + super(name, filter, layout, ignoreExceptions); > + thing = new SomethingThatUsesLogging(); > + } > + > + @PluginFactory > + public static UsesLoggingAppender > createAppender(@PluginAttribute("name") String name, > + > @PluginAttribute("ignoreExceptions") String ignore, > + @PluginElement("Layout") > Layout<?> layout, > + @PluginElement("Filters") Filter > filter) { > + > + boolean ignoreExceptions = Boolean.parseBoolean(ignore); > + > + if (name == null) { > + LOGGER.error("No name provided for MyAppender"); > + return null; > + } > + > + return new UsesLoggingAppender(name, filter, layout, > ignoreExceptions); > + } > + > + public void append(LogEvent event) { > + try { > + for (int i = 0; i < 50; i++) { > + Thread.sleep(10); > + thing.doSomething(); > + } > + } catch (InterruptedException e) { > + e.printStackTrace(); > + } > + // System.out.print("Log: " + getLayout().toSerializable(event)); > + } > +} > > Added: > logging/log4j/log4j2/trunk/log4j-core/src/test/resources/reconfiguration-deadlock.xml > URL: > http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/log4j-core/src/test/resources/reconfiguration-deadlock.xml?rev=1595741&view=auto > ============================================================================== > --- > logging/log4j/log4j2/trunk/log4j-core/src/test/resources/reconfiguration-deadlock.xml > (added) > +++ > logging/log4j/log4j2/trunk/log4j-core/src/test/resources/reconfiguration-deadlock.xml > Mon May 19 04:53:11 2014 > @@ -0,0 +1,19 @@ > +<?xml version="1.0" encoding="UTF-8"?> > +<Configuration status="error" monitorInterval="5"> > + <Appenders> > + <UsesLoggingAppender name="myAppender"> > + <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - > %msg%n" /> > + </UsesLoggingAppender> > + <Console name="STDOUT"> > + <PatternLayout pattern="%m%n"/> > + </Console> > + </Appenders> > + <Loggers> > + <Logger name="Dump" level="trace" additivity="false"> > + <AppenderRef ref="STDOUT" /> > + </Logger> > + <Root level="ERROR"> > + <AppenderRef ref="myAppender" /> > + </Root> > + </Loggers> > +</Configuration> > \ No newline at end of file > > Modified: logging/log4j/log4j2/trunk/src/changes/changes.xml > URL: > http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/src/changes/changes.xml?rev=1595741&r1=1595740&r2=1595741&view=diff > ============================================================================== > --- logging/log4j/log4j2/trunk/src/changes/changes.xml (original) > +++ logging/log4j/log4j2/trunk/src/changes/changes.xml Mon May 19 04:53:11 > 2014 > @@ -22,6 +22,9 @@ > </properties> > <body> > <release version="2.0-rc2" date="2014-MM-DD" description="Bug fixes and > enhancements"> > + <action issue="LOG4J2-620" dev="rgoers" type="fix"> > + Perform reconfiguration in a separate thread to prevent deadlocks. > + </action> > <action issue="LOG4J2-641" dev="mattsicker" type="update"> > Override commons-logging dependency version in tests. > </action> > > --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
