Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LogManager.Shutdown - Should disable file watcher and avoid auto reload #2616

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 34 additions & 29 deletions src/NLog/LogFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ public class LogFactory : IDisposable
{
#if !SILVERLIGHT && !__IOS__ && !__ANDROID__ && !NETSTANDARD1_3
private const int ReconfigAfterFileChangedTimeout = 1000;
internal Timer reloadTimer;
internal Timer _reloadTimer;
private readonly MultiFileWatcher _watcher;
#endif

Expand Down Expand Up @@ -200,7 +200,7 @@ public LoggingConfiguration Configuration

lock (_syncRoot)
{
if (_configLoaded)
if (_configLoaded || _isDisposing)
return _config;

#if !SILVERLIGHT && !__IOS__ && !__ANDROID__ && !NETSTANDARD
Expand Down Expand Up @@ -269,9 +269,7 @@ public LoggingConfiguration Configuration
if (oldConfig != null)
{
InternalLogger.Info("Closing old configuration.");
#if !SILVERLIGHT
Flush();
#endif
oldConfig.Close();
}

Expand Down Expand Up @@ -576,7 +574,6 @@ public void ReconfigExistingLoggers()
}
}

#if !SILVERLIGHT
/// <summary>
/// Flush any pending log messages (in case of asynchronous targets) with the default timeout of 15 seconds.
/// </summary>
Expand All @@ -603,7 +600,6 @@ public void Flush(TimeSpan timeout)
{
throw;
}

}
}

Expand All @@ -616,7 +612,6 @@ public void Flush(int timeoutMilliseconds)
{
Flush(TimeSpan.FromMilliseconds(timeoutMilliseconds));
}
#endif

/// <summary>
/// Flush any pending log messages (in case of asynchronous targets).
Expand Down Expand Up @@ -648,8 +643,11 @@ public void Flush(AsyncContinuation asyncContinuation, TimeSpan timeout)
try
{
InternalLogger.Trace("LogFactory.Flush({0})", timeout);

var loggingConfiguration = Configuration;
LoggingConfiguration loggingConfiguration = null;
lock (_syncRoot)
{
loggingConfiguration = _config; // Flush should not attempt to auto-load Configuration
}
if (loggingConfiguration != null)
{
loggingConfiguration.FlushAllTargets(AsyncHelpers.WithTimeout(asyncContinuation, timeout));
Expand Down Expand Up @@ -777,7 +775,7 @@ protected virtual void OnConfigurationReloaded(LoggingConfigurationReloadedEvent
#if !SILVERLIGHT && !__IOS__ && !__ANDROID__ && !NETSTANDARD1_3
internal void ReloadConfigOnTimer(object state)
{
if (reloadTimer == null && _isDisposing)
if (_reloadTimer == null && _isDisposing)
{
return; //timer was disposed already.
}
Expand All @@ -794,16 +792,16 @@ internal void ReloadConfigOnTimer(object state)
return; //timer was disposed already.
}

var currentTimer = reloadTimer;
var currentTimer = _reloadTimer;
if (currentTimer != null)
{
reloadTimer = null;
_reloadTimer = null;
currentTimer.WaitForDispose(TimeSpan.Zero);
}

_watcher.StopWatching();

if (Configuration != configurationToReload)
if (_config != configurationToReload)
{
throw new NLogConfigurationException("Config changed in between. Not reloading.");
}
Expand Down Expand Up @@ -962,6 +960,7 @@ private void Close(TimeSpan flushTimeout)
{
// Disable startup of new reload-timers
_watcher.FileChanged -= ConfigFileChanged;
_watcher.StopWatching();
}
#endif

Expand All @@ -970,10 +969,10 @@ private void Close(TimeSpan flushTimeout)
try
{
#if !SILVERLIGHT && !__IOS__ && !__ANDROID__ && !NETSTANDARD1_3
var currentTimer = reloadTimer;
var currentTimer = _reloadTimer;
if (currentTimer != null)
{
reloadTimer = null;
_reloadTimer = null;
currentTimer.WaitForDispose(TimeSpan.Zero);
}

Expand All @@ -1000,25 +999,30 @@ private void CloseOldConfig(TimeSpan flushTimeout, LoggingConfiguration oldConfi
{
try
{
#if !SILVERLIGHT && !__IOS__ && !__ANDROID__ && !NETSTANDARD1_3 && !MONO
bool attemptClose = true;
if (flushTimeout != TimeSpan.Zero && !PlatformDetector.IsMono)

#if !SILVERLIGHT && !__IOS__ && !__ANDROID__ && !NETSTANDARD1_3 && !MONO
if (flushTimeout != TimeSpan.Zero && !PlatformDetector.IsMono && !PlatformDetector.IsUnix)
{
// MONO (and friends) have a hard time with spinning up flush threads/timers during shutdown (Maybe better with MONO 4.1)
// MONO (and friends) have a hard time with spinning up flush threads/timers during shutdown
ManualResetEvent flushCompleted = new ManualResetEvent(false);
oldConfig.FlushAllTargets((ex) => flushCompleted.Set());
attemptClose = flushCompleted.WaitOne(flushTimeout);
}
#endif

// Disable all loggers, so things become quiet
_config = null;
ReconfigExistingLoggers();

if (!attemptClose)
{
InternalLogger.Warn("Target flush timeout. One or more targets did not complete flush operation, skipping target close.");
}
else
#endif
{
// Flush completed within timeout, lets try and close down
oldConfig.Close();
_config = null;
OnConfigurationChanged(new LoggingConfigurationChangedEventArgs(null, oldConfig));
}
}
Expand Down Expand Up @@ -1046,13 +1050,14 @@ internal void Shutdown()
InternalLogger.Info("Logger closing down...");
if (!_isDisposing && _configLoaded)
{
var loadedConfig = Configuration;
if (loadedConfig != null)
lock (_syncRoot)
{
ManualResetEvent flushCompleted = new ManualResetEvent(false);
loadedConfig.FlushAllTargets((ex) => flushCompleted.Set());
flushCompleted.WaitOne(DefaultFlushTimeout);
loadedConfig.Close();
if (_isDisposing || !_configLoaded)
return;

Configuration = null;
_configLoaded = true; // Locked disabled state
ReconfigExistingLoggers(); // Disable all loggers, so things become quiet
}
}
InternalLogger.Info("Logger has been closed down.");
Expand Down Expand Up @@ -1288,12 +1293,12 @@ private void ConfigFileChanged(object sender, EventArgs args)
return;
}

if (reloadTimer == null)
if (_reloadTimer == null)
{
var configuration = Configuration;
if (configuration != null)
{
reloadTimer = new Timer(
_reloadTimer = new Timer(
ReloadConfigOnTimer,
configuration,
ReconfigAfterFileChangedTimeout,
Expand All @@ -1302,7 +1307,7 @@ private void ConfigFileChanged(object sender, EventArgs args)
}
else
{
reloadTimer.Change(
_reloadTimer.Change(
ReconfigAfterFileChangedTimeout,
Timeout.Infinite);
}
Expand Down
2 changes: 1 addition & 1 deletion tests/NLog.UnitTests/Config/ReloadTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -685,7 +685,7 @@ public override LoggingConfiguration Reload()
var factory = LogManager.LogFactory;

//reloadTimer should be set for ReloadConfigOnTimer
factory.reloadTimer = new Timer((a) => { });
factory._reloadTimer = new Timer((a) => { });
factory.ReloadConfigOnTimer(this);
_reloading = false;
return factory.Configuration;
Expand Down