I still think that we should not use non-daemon threads (except in tests
and samples).

On Jan 12, 2017 11:45 PM, "Gary Gregory" <garydgreg...@gmail.com> wrote:

> I still like the work I did with executor services, so I'll leave it at
> that ;-) Sure it turns out there is a bug on reconfigure but it's fixable
> without throwing it all out. I'm swamped at work ATM so I cannot spend time
> dealing with too much FOSS this week (as was last week). Good luck :-)
>
> Gary
>
> On Thu, Jan 12, 2017 at 8: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> 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
>>> Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit
>>> /162a5e33
>>> Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/1
>>> 62a5e33
>>> Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/1
>>> 62a5e33
>>>
>>> Branch: refs/heads/LOG4J2-1748and1780-remove-ExecutorService-from-Lo
>>> ggerContext
>>> Commit: 162a5e33ace3f1b4adf0726502083d0efb1e799a
>>> Parents: a6f9d12
>>> Author: Mikael Ståldal <mikael.stal...@magine.com>
>>> Authored: Thu Jan 12 12:14:18 2017 +0100
>>> Committer: Mikael Ståldal <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/1
>>> 62a5e33/log4j-core/src/main/java/org/apache/logging/log4j/co
>>> re/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/Log
>>> gerContext.java
>>> index 2322376..9797cc6 100644
>>> --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/Log
>>> gerContext.java
>>> +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/Log
>>> gerContext.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(Log4
>>> jThreadFactory.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/1
>>> 62a5e33/log4j-core/src/main/java/org/apache/logging/log4j/co
>>> re/appender/mom/kafka/KafkaManager.java
>>> ----------------------------------------------------------------------
>>> diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/app
>>> ender/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/app
>>> ender/mom/kafka/KafkaManager.java
>>> +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/app
>>> ender/mom/kafka/KafkaManager.java
>>> @@ -30,6 +30,7 @@ import org.apache.kafka.clients.produ
>>> cer.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
>>> -            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/1
>>> 62a5e33/log4j-core/src/main/java/org/apache/logging/log4j/co
>>> re/appender/rolling/RollingFileManager.java
>>> ----------------------------------------------------------------------
>>> diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/app
>>> ender/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/app
>>> ender/rolling/RollingFileManager.java
>>> +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/app
>>> ender/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/1
>>> 62a5e33/log4j-core/src/main/java/org/apache/logging/log4j/co
>>> re/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/con
>>> fig/AbstractConfiguration.java
>>> index 3a6a58e..e5e149e 100644
>>> --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/con
>>> fig/AbstractConfiguration.java
>>> +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/con
>>> fig/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/1
>>> 62a5e33/log4j-core/src/main/java/org/apache/logging/log4j/co
>>> re/config/ConfigurationScheduler.java
>>> ----------------------------------------------------------------------
>>> diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/con
>>> fig/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/con
>>> fig/ConfigurationScheduler.java
>>> +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/con
>>> fig/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.createDaemo
>>> nThreadFactory("Scheduled"));
>>> -                executor.setContinueExistingPe
>>> riodicTasksAfterShutdownPolicy(false);
>>> -                executor.setExecuteExistingDel
>>> ayedTasksAfterShutdownPolicy(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.createDaemo
>>> nThreadFactory("Scheduled"));
>>> +            executor.setContinueExistingPe
>>> riodicTasksAfterShutdownPolicy(false);
>>> +            executor.setExecuteExistingDel
>>> ayedTasksAfterShutdownPolicy(false);
>>> +            this.executorService = executor;
>>>          }
>>>          return executorService;
>>>      }
>>>
>>> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/1
>>> 62a5e33/log4j-core/src/main/java/org/apache/logging/log4j/co
>>> re/config/ConfiguratonFileWatcher.java
>>> ----------------------------------------------------------------------
>>> diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/con
>>> fig/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/con
>>> fig/ConfiguratonFileWatcher.java
>>> +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/con
>>> fig/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.createDaemo
>>> nThreadFactory("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/1
>>> 62a5e33/log4j-core/src/main/java/org/apache/logging/log4j/co
>>> re/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/con
>>> fig/Configurator.java
>>> index 28dd85f..63d8a81 100644
>>> --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/con
>>> fig/Configurator.java
>>> +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/con
>>> fig/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/1
>>> 62a5e33/log4j-core/src/main/java/org/apache/logging/log4j/co
>>> re/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/uti
>>> l/Log4jThreadFactory.java
>>> index 3715243..2318feb 100644
>>> --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/uti
>>> l/Log4jThreadFactory.java
>>> +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/uti
>>> l/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/1
>>> 62a5e33/log4j-nosql/src/test/java/org/apache/logging/log4j/n
>>> osql/appender/cassandra/CassandraRule.java
>>> ----------------------------------------------------------------------
>>> diff --git a/log4j-nosql/src/test/java/org/apache/logging/log4j/nosql/a
>>> ppender/cassandra/CassandraRule.java b/log4j-nosql/src/test/java/or
>>> g/apache/logging/log4j/nosql/appender/cassandra/CassandraRule.java
>>> index bec97ea..900f794 100644
>>> --- a/log4j-nosql/src/test/java/org/apache/logging/log4j/nosql/a
>>> ppender/cassandra/CassandraRule.java
>>> +++ b/log4j-nosql/src/test/java/org/apache/logging/log4j/nosql/a
>>> ppender/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/1
>>> 62a5e33/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/sit
>>> e/apidocs/org/apache/logging/log4j/core/LoggerContext.html#stop(long,
>>> java.util.concurrent.TimeUnit)">LoggerContext.stop(long,
>>> java.util.concurrent.TimeUnit)</a>.
>>>
>>>
>>
>
>
> --
> E-Mail: garydgreg...@gmail.com | ggreg...@apache.org
> Java Persistence with Hibernate, Second Edition
> <https://www.amazon.com/gp/product/1617290459/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1617290459&linkCode=as2&tag=garygregory-20&linkId=cadb800f39946ec62ea2b1af9fe6a2b8>
>
> <http:////ir-na.amazon-adsystem.com/e/ir?t=garygregory-20&l=am2&o=1&a=1617290459>
> JUnit in Action, Second Edition
> <https://www.amazon.com/gp/product/1935182021/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1935182021&linkCode=as2&tag=garygregory-20&linkId=31ecd1f6b6d1eaf8886ac902a24de418%22>
>
> <http:////ir-na.amazon-adsystem.com/e/ir?t=garygregory-20&l=am2&o=1&a=1935182021>
> Spring Batch in Action
> <https://www.amazon.com/gp/product/1935182951/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1935182951&linkCode=%7B%7BlinkCode%7D%7D&tag=garygregory-20&linkId=%7B%7Blink_id%7D%7D%22%3ESpring+Batch+in+Action>
> <http:////ir-na.amazon-adsystem.com/e/ir?t=garygregory-20&l=am2&o=1&a=1935182951>
> Blog: http://garygregory.wordpress.com
> Home: http://garygregory.com/
> Tweet! http://twitter.com/GaryGregory
>

Reply via email to