Item 1 - It should not be removed.
Item 2 - The RollingFileAppender could increment the scheduled items if an 
instance is configured. Ideally, it should only increment it once.
Item 3 - It might make more sense for the RollingFileManager to use a  
ThreadPoolExecutorService that it owns for the async task.
Item 4 - I will have to look into this one.

Ralph

> On Jan 12, 2017, at 9:01 AM, Remko Popma <remko.po...@gmail.com> wrote:
> 
> Some feedback:
> 1. Why remove Log4jThreadFactory.createThreadFactory?
> CassandraRule was using it and now needs to use the constructor.
> 
> 2. The ConfigurationScheduler may create a thread pool with size zero.  
> ConfigurationScheduler::incrementScheduledItems is only called if 
> monitorInterval is positive, or if a plugin with the @Scheduled annotation is 
> configured (not sure I'm reading that right), or if a CronTriggeringPolicy is 
> configured. If none of these are true, but a RollingFile appender is 
> configured, I think there will be a problem. 
> 
> 3. Generally, I think RollingFileManager AsyncActions (compress) should not 
> be submitted to the ConfigurationScheduler: this executor will usually only 
> have one thread so these actions will execute one by one sequentially. If 
> many files need to be rolled over and compressed at the same time, I think 
> this work should be done in parallel as much as possible.Therefore, I think 
> it's better to create new (non-daemon) threads for the rollover async actions.
> 
> 4. (Not your change, I noticed during review): ConfigurationScheduler catches 
> InterruptedException but does not restore the interrupted flag. Should be:
> ...
> } catch (InterruptedException ie) {
> ...
>     // Preserve interrupt status
>     Thread.currentThread().interrupt();
> }
> 
> 
> On Thu, Jan 12, 2017 at 8:36 PM, <mi...@apache.org <mailto:mi...@apache.org>> 
> wrote:
> Repository: logging-log4j2
> Updated Branches:
>   refs/heads/LOG4J2-1748and1780-remove-ExecutorService-from-LoggerContext 
> [created] 162a5e33a
> 
> 
> LOG4J2-1748 and LOG4J2-1780 Remove ExecutorServices from LoggerContext
> 
> 
> Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo 
> <http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo>
> Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/162a5e33 
> <http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/162a5e33>
> Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/162a5e33 
> <http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/162a5e33>
> Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/162a5e33 
> <http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/162a5e33>
> 
> Branch: 
> refs/heads/LOG4J2-1748and1780-remove-ExecutorService-from-LoggerContext
> Commit: 162a5e33ace3f1b4adf0726502083d0efb1e799a
> Parents: a6f9d12
> Author: Mikael Ståldal <mikael.stal...@magine.com 
> <mailto:mikael.stal...@magine.com>>
> Authored: Thu Jan 12 12:14:18 2017 +0100
> Committer: Mikael Ståldal <mikael.stal...@magine.com 
> <mailto:mikael.stal...@magine.com>>
> Committed: Thu Jan 12 12:32:00 2017 +0100
> 
> ----------------------------------------------------------------------
>  .../logging/log4j/core/LoggerContext.java       | 97 +-------------------
>  .../core/appender/mom/kafka/KafkaManager.java   | 11 ++-
>  .../appender/rolling/RollingFileManager.java    |  2 +-
>  .../core/config/AbstractConfiguration.java      |  4 +-
>  .../core/config/ConfigurationScheduler.java     | 51 +++++++---
>  .../core/config/ConfiguratonFileWatcher.java    |  7 +-
>  .../logging/log4j/core/config/Configurator.java |  4 +-
>  .../log4j/core/util/Log4jThreadFactory.java     | 11 ---
>  .../nosql/appender/cassandra/CassandraRule.java |  2 +-
>  src/site/xdoc/manual/configuration.xml.vm       |  4 +-
>  10 files changed, 59 insertions(+), 134 deletions(-)
> ----------------------------------------------------------------------
> 
> 
> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/162a5e33/log4j-core/src/main/java/org/apache/logging/log4j/core/LoggerContext.java
>  
> <http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/162a5e33/log4j-core/src/main/java/org/apache/logging/log4j/core/LoggerContext.java>
> ----------------------------------------------------------------------
> diff --git 
> a/log4j-core/src/main/java/org/apache/logging/log4j/core/LoggerContext.java 
> b/log4j-core/src/main/java/org/apache/logging/log4j/core/LoggerContext.java
> index 2322376..9797cc6 100644
> --- 
> a/log4j-core/src/main/java/org/apache/logging/log4j/core/LoggerContext.java
> +++ 
> b/log4j-core/src/main/java/org/apache/logging/log4j/core/LoggerContext.java
> @@ -26,13 +26,6 @@ import java.util.Collection;
>  import java.util.Objects;
>  import java.util.concurrent.ConcurrentMap;
>  import java.util.concurrent.CopyOnWriteArrayList;
> -import java.util.concurrent.ExecutorService;
> -import java.util.concurrent.Executors;
> -import java.util.concurrent.Future;
> -import java.util.concurrent.RejectedExecutionException;
> -import java.util.concurrent.SynchronousQueue;
> -import java.util.concurrent.ThreadFactory;
> -import java.util.concurrent.ThreadPoolExecutor;
>  import java.util.concurrent.TimeUnit;
>  import java.util.concurrent.locks.Lock;
>  import java.util.concurrent.locks.ReentrantLock;
> @@ -49,7 +42,6 @@ import org.apache.logging.log4j.core.impl.Log4jLogEvent;
>  import org.apache.logging.log4j.core.jmx.Server;
>  import org.apache.logging.log4j.core.util.Cancellable;
>  import org.apache.logging.log4j.core.util.ExecutorServices;
> -import org.apache.logging.log4j.core.util.Log4jThreadFactory;
>  import org.apache.logging.log4j.core.util.NetUtils;
>  import org.apache.logging.log4j.core.util.ShutdownCallbackRegistry;
>  import org.apache.logging.log4j.message.MessageFactory;
> @@ -92,8 +84,6 @@ public class LoggerContext extends AbstractLifeCycle
>       * reference is updated.
>       */
>      private volatile Configuration configuration = new 
> DefaultConfiguration();
> -    private ExecutorService executorService;
> -    private ExecutorService executorServiceDeamons;
>      private Object externalContext;
>      private String contextName;
>      private volatile URI configLocation;
> @@ -326,8 +316,8 @@ public class LoggerContext extends AbstractLifeCycle
>       * Log4j can start threads to perform certain actions like file 
> rollovers, calling this method with a positive timeout will
>       * block until the rollover thread is done.
>       *
> -     * @param timeout the maximum time to wait, or 0 which mean that each 
> apppender uses its default timeout, and don't wait for background
> -    tasks
> +     * @param timeout the maximum time to wait, or 0 which mean that each 
> apppender uses its default timeout, and wait for
> +     *                background tasks for one second
>       * @param timeUnit
>       *            the time unit of the timeout argument
>       * @return {@code true} if the logger context terminated and {@code 
> false} if the timeout elapsed before
> @@ -338,8 +328,6 @@ public class LoggerContext extends AbstractLifeCycle
>      public boolean stop(final long timeout, final TimeUnit timeUnit) {
>          LOGGER.debug("Stopping LoggerContext[name={}, {}]...", getName(), 
> this);
>          configLock.lock();
> -        final boolean shutdownEs;
> -        final boolean shutdownEsd;
>          try {
>              if (this.isStopped()) {
>                  return true;
> @@ -366,16 +354,12 @@ public class LoggerContext extends AbstractLifeCycle
>              }
>              externalContext = null;
>              LogManager.getFactory().removeContext(this);
> -            final String source = "LoggerContext \'" + getName() + "\'";
> -            shutdownEs = ExecutorServices.shutdown(executorService, timeout, 
> timeUnit, source);
> -            // Do not wait for daemon threads
> -            shutdownEsd = ExecutorServices.shutdown(executorServiceDeamons, 
> 0, timeUnit, source);
>          } finally {
>              configLock.unlock();
>              this.setStopped();
>          }
>          LOGGER.debug("Stopped LoggerContext[name={}, {}]...", getName(), 
> this);
> -        return shutdownEs && shutdownEsd;
> +        return true;
>      }
> 
>      /**
> @@ -548,9 +532,6 @@ public class LoggerContext extends AbstractLifeCycle
>          try {
>              final Configuration prev = this.configuration;
>              config.addListener(this);
> -            executorService = 
> createNonDaemonThreadPool(Log4jThreadFactory.createThreadFactory(contextName));
> -            // Daemon threads do not prevent the application from shutting 
> down so the default keep-alive time is fine.
> -            executorServiceDeamons = 
> Executors.newCachedThreadPool(Log4jThreadFactory.createDaemonThreadFactory(contextName));
> 
>              final ConcurrentMap<String, String> map = 
> config.getComponent(Configuration.CONTEXT_PROPERTIES);
> 
> @@ -586,30 +567,6 @@ public class LoggerContext extends AbstractLifeCycle
>          }
>      }
> 
> -    /**
> -     * Returns an {@code ExecutorService} whose keep-alive time is one 
> second by default, unless another
> -     * value is specified for system property {@code 
> log4j.nondaemon.threads.keepAliveSeconds}.
> -     * <p>
> -     * LOG4J2-1748: ThreadPool for non-daemon threads should use a short 
> keep-alive time to prevent
> -     * applications from being able to shut down promptly after a rollover.
> -     * </p>
> -     *
> -     * @param threadFactory thread factory to use
> -     * @return a new cached thread pool
> -     */
> -    private ExecutorService createNonDaemonThreadPool(final ThreadFactory 
> threadFactory) {
> -        final String PROP = "log4j.nondaemon.threads.keepAliveSeconds";
> -        final int keepAliveTimeSeconds = 
> PropertiesUtil.getProperties().getIntegerProperty(PROP, 1);
> -        return createThreadPool(threadFactory, keepAliveTimeSeconds);
> -    }
> -
> -    private ExecutorService createThreadPool(final ThreadFactory 
> threadFactory, final int keepAliveTimeSeconds) {
> -        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
> -                keepAliveTimeSeconds, TimeUnit.SECONDS,
> -                new SynchronousQueue<Runnable>(),
> -                threadFactory);
> -    }
> -
>      private void firePropertyChangeEvent(final PropertyChangeEvent event) {
>          for (final PropertyChangeListener listener : 
> propertyChangeListeners) {
>              listener.propertyChange(event);
> @@ -719,52 +676,4 @@ public class LoggerContext extends AbstractLifeCycle
>          return new Logger(ctx, name, messageFactory);
>      }
> 
> -    /**
> -     * Gets the executor service to submit normal tasks.
> -     *
> -     * @return the ExecutorService to submit normal tasks.
> -     */
> -    public ExecutorService getExecutorService() {
> -        return executorService;
> -    }
> -
> -    /**
> -     * Gets the executor service to submit daemon tasks.
> -     *
> -     * @return the ExecutorService to submit normal daemon tasks.
> -     */
> -    public ExecutorService getExecutorServiceDeamons() {
> -        return executorServiceDeamons;
> -    }
> -
> -    /**
> -     * Submits a Runnable task for normal execution and returns a Future 
> representing that task. The Future's
> -     * {@code get} method will return {@code null} upon <em>successful</em> 
> completion.
> -     *
> -     * @param task the task to submit
> -     * @return a Future representing pending completion of the task
> -     * @throws RejectedExecutionException if the task cannot be
> -     *         scheduled for execution
> -     * @throws NullPointerException if the task is null
> -     */
> -    public Future<?> submit(final Runnable task) {
> -        return executorService.submit(task);
> -    }
> -
> -    /**
> -     * Submits a Runnable task for daemon execution and returns a Future 
> representing that task. The Future's
> -     * {@code get} method will return {@code null} upon <em>successful</em> 
> completion.
> -     *
> -     * @param task
> -     *            the task to submit
> -     * @return a Future representing pending completion of the task
> -     * @throws RejectedExecutionException
> -     *             if the task cannot be scheduled for execution
> -     * @throws NullPointerException
> -     *             if the task is null
> -     */
> -    public Future<?> submitDaemon(final Runnable task) {
> -        return executorServiceDeamons.submit(task);
> -    }
> -
>  }
> 
> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/162a5e33/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/mom/kafka/KafkaManager.java
>  
> <http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/162a5e33/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/mom/kafka/KafkaManager.java>
> ----------------------------------------------------------------------
> diff --git 
> a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/mom/kafka/KafkaManager.java
>  
> b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/mom/kafka/KafkaManager.java
> index 616191c..b293f2a 100644
> --- 
> a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/mom/kafka/KafkaManager.java
> +++ 
> b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/mom/kafka/KafkaManager.java
> @@ -30,6 +30,7 @@ import org.apache.kafka.clients.producer.RecordMetadata;
>  import org.apache.logging.log4j.core.LoggerContext;
>  import org.apache.logging.log4j.core.appender.AbstractManager;
>  import org.apache.logging.log4j.core.config.Property;
> +import org.apache.logging.log4j.core.util.Log4jThread;
> 
>  public class KafkaManager extends AbstractManager {
> 
> @@ -73,17 +74,19 @@ public class KafkaManager extends AbstractManager {
>      private void closeProducer(final long timeout, final TimeUnit timeUnit) {
>          if (producer != null) {
>              // This thread is a workaround for this Kafka issue: 
> https://issues.apache.org/jira/browse/KAFKA-1660 
> <https://issues.apache.org/jira/browse/KAFKA-1660>
> -            final Runnable task = new Runnable() {
> +           final Thread closeThread = new Log4jThread(new Runnable() {
>                  @Override
>                  public void run() {
>                      if (producer != null) {
>                          producer.close();
>                      }
>                  }
> -            };
> +            }, "KafkaManager-CloseThread");
> +            closeThread.setDaemon(true); // avoid blocking JVM shutdown
> +            closeThread.start();
>              try {
> -                getLoggerContext().submitDaemon(task).get(timeout, timeUnit);
> -            } catch (InterruptedException | ExecutionException | 
> TimeoutException e) {
> +                closeThread.join(timeUnit.toMillis(timeout));
> +            } catch (final InterruptedException ignore) {
>                  // ignore
>              }
>          }
> 
> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/162a5e33/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/RollingFileManager.java
>  
> <http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/162a5e33/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/RollingFileManager.java>
> ----------------------------------------------------------------------
> diff --git 
> a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/RollingFileManager.java
>  
> b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/RollingFileManager.java
> index 10cb79e..e9c7790 100644
> --- 
> a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/RollingFileManager.java
> +++ 
> b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/RollingFileManager.java
> @@ -296,7 +296,7 @@ public class RollingFileManager extends FileManager {
> 
>                  if (success && descriptor.getAsynchronous() != null) {
>                      LOGGER.debug("RollingFileManager executing async {}", 
> descriptor.getAsynchronous());
> -                    future = LoggerContext.getContext(false).submit(new 
> AsyncAction(descriptor.getAsynchronous(), this));
> +                    future = 
> LoggerContext.getContext(false).getConfiguration().getScheduler().submit(new 
> AsyncAction(descriptor.getAsynchronous(), this));
>                  }
>                  return true;
>              }
> 
> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/162a5e33/log4j-core/src/main/java/org/apache/logging/log4j/core/config/AbstractConfiguration.java
>  
> <http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/162a5e33/log4j-core/src/main/java/org/apache/logging/log4j/core/config/AbstractConfiguration.java>
> ----------------------------------------------------------------------
> diff --git 
> a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/AbstractConfiguration.java
>  
> b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/AbstractConfiguration.java
> index 3a6a58e..e5e149e 100644
> --- 
> a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/AbstractConfiguration.java
> +++ 
> b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/AbstractConfiguration.java
> @@ -373,9 +373,9 @@ public abstract class AbstractConfiguration extends 
> AbstractFilterable implement
>          root.clearAppenders();
> 
>          if (watchManager.isStarted()) {
> -            watchManager.stop();
> +            watchManager.stop(timeout, timeUnit);
>          }
> -        configurationScheduler.stop();
> +        configurationScheduler.stop(timeout, timeUnit);
> 
>          if (advertiser != null && advertisement != null) {
>              advertiser.unadvertise(advertisement);
> 
> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/162a5e33/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ConfigurationScheduler.java
>  
> <http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/162a5e33/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ConfigurationScheduler.java>
> ----------------------------------------------------------------------
> diff --git 
> a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ConfigurationScheduler.java
>  
> b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ConfigurationScheduler.java
> index 6c639f2..4af83a5 100644
> --- 
> a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ConfigurationScheduler.java
> +++ 
> b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ConfigurationScheduler.java
> @@ -17,9 +17,9 @@
>  package org.apache.logging.log4j.core.config;
> 
>  import java.util.Date;
> -import java.util.List;
>  import java.util.Queue;
>  import java.util.concurrent.Callable;
> +import java.util.concurrent.Future;
>  import java.util.concurrent.ScheduledExecutorService;
>  import java.util.concurrent.ScheduledFuture;
>  import java.util.concurrent.ScheduledThreadPoolExecutor;
> @@ -39,6 +39,7 @@ public class ConfigurationScheduler extends 
> AbstractLifeCycle {
>      private static final Logger LOGGER = StatusLogger.getLogger();
>      private static final String SIMPLE_NAME = "Log4j2 " + 
> ConfigurationScheduler.class.getSimpleName();
>      private static final int MAX_SCHEDULED_ITEMS = 5;
> +    private static final long DEFAULT_SHUTDOWN_TIMEOUT_MILLIS = 1000;
>      private ScheduledExecutorService executorService;
> 
>      private int scheduledItems = 0;
> @@ -52,14 +53,17 @@ public class ConfigurationScheduler extends 
> AbstractLifeCycle {
>      public boolean stop(final long timeout, final TimeUnit timeUnit) {
>          setStopping();
>          if (isExecutorServiceSet()) {
> +            long timeoutToUse = timeout > 0 ? timeout : 
> DEFAULT_SHUTDOWN_TIMEOUT_MILLIS;
> +            TimeUnit timeUnitToUse = timeout > 0 ? timeUnit : 
> TimeUnit.MILLISECONDS;
> +
>              LOGGER.debug("{} shutting down threads in {}", SIMPLE_NAME, 
> getExecutorService());
>              executorService.shutdown();
>              try {
> -                executorService.awaitTermination(timeout, timeUnit);
> +                executorService.awaitTermination(timeoutToUse, 
> timeUnitToUse);
>              } catch (InterruptedException ie) {
>                  executorService.shutdownNow();
>                  try {
> -                    executorService.awaitTermination(timeout, timeUnit);
> +                    executorService.awaitTermination(timeoutToUse, 
> timeUnitToUse);
>                  } catch (InterruptedException inner) {
>                      LOGGER.warn("ConfigurationScheduler stopped but some 
> scheduled services may not have completed.");
>                  }
> @@ -95,6 +99,28 @@ public class ConfigurationScheduler extends 
> AbstractLifeCycle {
>      }
> 
>      /**
> +     * Creates and executes a Future that becomes enabled immediately.
> +     * @param <V> The result type returned by this Future
> +     * @param callable the function to execute.
> +     * @return a Future that can be used to extract result or cancel.
> +     *
> +     */
> +    public <V> Future<V> submit(final Callable<V> callable) {
> +        return getExecutorService().submit(callable);
> +    }
> +
> +    /**
> +     * Creates and executes a Future that becomes enabled immediately.
> +     * @param runnable the function to execute.
> +     * @return a Future representing pending completion of the task and 
> whose get() method will return null
> +     * upon completion.
> +     */
> +    public Future<?> submit(final Runnable runnable) {
> +        return getExecutorService().submit(runnable);
> +    }
> +
> +
> +    /**
>       * Creates and executes a ScheduledFuture that becomes enabled after the 
> given delay.
>       * @param <V> The result type returned by this Future
>       * @param callable the function to execute.
> @@ -183,18 +209,13 @@ public class ConfigurationScheduler extends 
> AbstractLifeCycle {
> 
>      private ScheduledExecutorService getExecutorService() {
>          if (executorService == null) {
> -            if (scheduledItems > 0) {
> -                LOGGER.debug("{} starting {} threads", SIMPLE_NAME, 
> scheduledItems);
> -                scheduledItems = Math.min(scheduledItems, 
> MAX_SCHEDULED_ITEMS);
> -                ScheduledThreadPoolExecutor executor = new 
> ScheduledThreadPoolExecutor(scheduledItems,
> -                        
> Log4jThreadFactory.createDaemonThreadFactory("Scheduled"));
> -                
> executor.setContinueExistingPeriodicTasksAfterShutdownPolicy(false);
> -                
> executor.setExecuteExistingDelayedTasksAfterShutdownPolicy(false);
> -                this.executorService = executor;
> -
> -            } else {
> -                LOGGER.debug("{}: No scheduled items", SIMPLE_NAME);
> -            }
> +            LOGGER.debug("{} starting {} threads", SIMPLE_NAME, 
> scheduledItems);
> +            scheduledItems = Math.min(scheduledItems, MAX_SCHEDULED_ITEMS);
> +            ScheduledThreadPoolExecutor executor = new 
> ScheduledThreadPoolExecutor(scheduledItems + 1,
> +                    
> Log4jThreadFactory.createDaemonThreadFactory("Scheduled"));
> +            
> executor.setContinueExistingPeriodicTasksAfterShutdownPolicy(false);
> +            
> executor.setExecuteExistingDelayedTasksAfterShutdownPolicy(false);
> +            this.executorService = executor;
>          }
>          return executorService;
>      }
> 
> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/162a5e33/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ConfiguratonFileWatcher.java
>  
> <http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/162a5e33/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ConfiguratonFileWatcher.java>
> ----------------------------------------------------------------------
> diff --git 
> a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ConfiguratonFileWatcher.java
>  
> b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ConfiguratonFileWatcher.java
> index b32f9d0..38491f2 100644
> --- 
> a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ConfiguratonFileWatcher.java
> +++ 
> b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ConfiguratonFileWatcher.java
> @@ -19,8 +19,8 @@ package org.apache.logging.log4j.core.config;
>  import java.io.File;
>  import java.util.List;
> 
> -import org.apache.logging.log4j.core.LoggerContext;
>  import org.apache.logging.log4j.core.util.FileWatcher;
> +import org.apache.logging.log4j.core.util.Log4jThreadFactory;
> 
>  /**
>   * Watcher for configuration files. Causes a reconfiguration when a file 
> changes.
> @@ -29,10 +29,12 @@ public class ConfiguratonFileWatcher implements 
> FileWatcher {
> 
>      private final Reconfigurable reconfigurable;
>      private final List<ConfigurationListener> configurationListeners;
> +    private final Log4jThreadFactory threadFactory;
> 
>      public ConfiguratonFileWatcher(final Reconfigurable reconfigurable, 
> final List<ConfigurationListener> configurationListeners) {
>          this.reconfigurable = reconfigurable;
>          this.configurationListeners = configurationListeners;
> +        this.threadFactory = 
> Log4jThreadFactory.createDaemonThreadFactory("ConfiguratonFileWatcher");
>      }
> 
>      public List<ConfigurationListener> getListeners() {
> @@ -43,7 +45,8 @@ public class ConfiguratonFileWatcher implements FileWatcher 
> {
>      @Override
>      public void fileModified(final File file) {
>          for (final ConfigurationListener configurationListener : 
> configurationListeners) {
> -            LoggerContext.getContext(false).submitDaemon(new 
> ReconfigurationRunnable(configurationListener, reconfigurable));
> +            final Thread thread = threadFactory.newThread(new 
> ReconfigurationRunnable(configurationListener, reconfigurable));
> +            thread.start();
>          }
>      }
> 
> 
> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/162a5e33/log4j-core/src/main/java/org/apache/logging/log4j/core/config/Configurator.java
>  
> <http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/162a5e33/log4j-core/src/main/java/org/apache/logging/log4j/core/config/Configurator.java>
> ----------------------------------------------------------------------
> diff --git 
> a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/Configurator.java
>  
> b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/Configurator.java
> index 28dd85f..63d8a81 100644
> --- 
> a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/Configurator.java
> +++ 
> b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/Configurator.java
> @@ -331,8 +331,8 @@ public final class Configurator {
>      /**
>       * Shuts down the given logger context. This request does not wait for 
> Log4j tasks to complete.
>       * <p>
> -     * Log4j starts threads to perform certain actions like file rollovers; 
> calling this method will not wait until the
> -     * rollover thread is done. When this method returns, these tasks' 
> status are undefined, the tasks may be done or
> +     * Log4j starts threads to perform certain actions like file rollovers; 
> calling this method will wait up to one second
> +     * until the rollover thread is done. When this method returns, these 
> tasks' status are undefined, the tasks may be done or
>       * not.
>       * </p>
>       *
> 
> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/162a5e33/log4j-core/src/main/java/org/apache/logging/log4j/core/util/Log4jThreadFactory.java
>  
> <http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/162a5e33/log4j-core/src/main/java/org/apache/logging/log4j/core/util/Log4jThreadFactory.java>
> ----------------------------------------------------------------------
> diff --git 
> a/log4j-core/src/main/java/org/apache/logging/log4j/core/util/Log4jThreadFactory.java
>  
> b/log4j-core/src/main/java/org/apache/logging/log4j/core/util/Log4jThreadFactory.java
> index 3715243..2318feb 100644
> --- 
> a/log4j-core/src/main/java/org/apache/logging/log4j/core/util/Log4jThreadFactory.java
> +++ 
> b/log4j-core/src/main/java/org/apache/logging/log4j/core/util/Log4jThreadFactory.java
> @@ -40,17 +40,6 @@ public class Log4jThreadFactory implements ThreadFactory {
>          return new Log4jThreadFactory(threadFactoryName, true, 
> Thread.NORM_PRIORITY);
>      }
> 
> -    /**
> -     * Creates a new thread factory.
> -     *
> -     * @param threadFactoryName
> -     *            The thread factory name.
> -     * @return a new daemon thread factory.
> -     */
> -    public static Log4jThreadFactory createThreadFactory(final String 
> threadFactoryName) {
> -        return new Log4jThreadFactory(threadFactoryName, false, 
> Thread.NORM_PRIORITY);
> -    }
> -
>      private static final AtomicInteger FACTORY_NUMBER = new AtomicInteger(1);
>      private static final AtomicInteger THREAD_NUMBER = new AtomicInteger(1);
>      private final boolean daemon;
> 
> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/162a5e33/log4j-nosql/src/test/java/org/apache/logging/log4j/nosql/appender/cassandra/CassandraRule.java
>  
> <http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/162a5e33/log4j-nosql/src/test/java/org/apache/logging/log4j/nosql/appender/cassandra/CassandraRule.java>
> ----------------------------------------------------------------------
> diff --git 
> a/log4j-nosql/src/test/java/org/apache/logging/log4j/nosql/appender/cassandra/CassandraRule.java
>  
> b/log4j-nosql/src/test/java/org/apache/logging/log4j/nosql/appender/cassandra/CassandraRule.java
> index bec97ea..900f794 100644
> --- 
> a/log4j-nosql/src/test/java/org/apache/logging/log4j/nosql/appender/cassandra/CassandraRule.java
> +++ 
> b/log4j-nosql/src/test/java/org/apache/logging/log4j/nosql/appender/cassandra/CassandraRule.java
> @@ -37,7 +37,7 @@ import org.junit.rules.ExternalResource;
>   */
>  public class CassandraRule extends ExternalResource {
> 
> -    private static final ThreadFactory THREAD_FACTORY = 
> Log4jThreadFactory.createThreadFactory("Cassandra");
> +    private static final ThreadFactory THREAD_FACTORY = new 
> Log4jThreadFactory("Cassandra", false, Thread.NORM_PRIORITY);
> 
>      private final CountDownLatch latch = new CountDownLatch(1);
>      private final Cancellable embeddedCassandra = new 
> EmbeddedCassandra(latch);
> 
> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/162a5e33/src/site/xdoc/manual/configuration.xml.vm
>  
> <http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/162a5e33/src/site/xdoc/manual/configuration.xml.vm>
> ----------------------------------------------------------------------
> diff --git a/src/site/xdoc/manual/configuration.xml.vm 
> b/src/site/xdoc/manual/configuration.xml.vm
> index ec73bac..3075839 100644
> --- a/src/site/xdoc/manual/configuration.xml.vm
> +++ b/src/site/xdoc/manual/configuration.xml.vm
> @@ -410,8 +410,8 @@ public class Bar {
>                <tr>
>                   <td>shutdownTimeout</td>
>                   <td>Specifies how many milliseconds appenders and 
> background tasks will get to shutdown when the JVM shuts
> -                 down. Default is zero which mean that each appender uses 
> its default timeout, and don't wait for background
> -                 tasks. Not all appenders will honor this, it is a hint and 
> not an absolute guarantee that the shutdown
> +                 down. Default is zero which mean that each appender uses 
> its default timeout, and wait for background
> +                 tasks for one second. Not all appenders will honor this, it 
> is a hint and not an absolute guarantee that the shutdown
>                   procedure will not take longer. Setting this too low 
> increase the risk of losing outstanding log events
>                   not yet written to the final destination. See <a 
> class="javadoc"
>                   
> href="../log4j-core/target/site/apidocs/org/apache/logging/log4j/core/LoggerContext.html#stop(long,
>  java.util.concurrent.TimeUnit)">LoggerContext.stop(long, 
> java.util.concurrent.TimeUnit)</a>.
> 
> 

Reply via email to