prevent DOS in directory watchers

This commit is contained in:
Luke Pulverenti 2013-09-19 11:13:34 -04:00
parent d580abcd65
commit 9e91e3b2dd

View File

@ -6,6 +6,7 @@ using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Entities; using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging; using MediaBrowser.Model.Logging;
using MediaBrowser.Server.Implementations.ScheduledTasks; using MediaBrowser.Server.Implementations.ScheduledTasks;
using Microsoft.Win32;
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
@ -24,7 +25,7 @@ namespace MediaBrowser.Server.Implementations.IO
/// <summary> /// <summary>
/// The file system watchers /// The file system watchers
/// </summary> /// </summary>
private readonly ConcurrentDictionary<string, FileSystemWatcher> _fileSystemWatchers = new ConcurrentDictionary<string,FileSystemWatcher>(StringComparer.OrdinalIgnoreCase); private readonly ConcurrentDictionary<string, FileSystemWatcher> _fileSystemWatchers = new ConcurrentDictionary<string, FileSystemWatcher>(StringComparer.OrdinalIgnoreCase);
/// <summary> /// <summary>
/// The update timer /// The update timer
/// </summary> /// </summary>
@ -100,6 +101,19 @@ namespace MediaBrowser.Server.Implementations.IO
TaskManager = taskManager; TaskManager = taskManager;
Logger = logManager.GetLogger("DirectoryWatchers"); Logger = logManager.GetLogger("DirectoryWatchers");
ConfigurationManager = configurationManager; ConfigurationManager = configurationManager;
SystemEvents.PowerModeChanged += SystemEvents_PowerModeChanged;
}
/// <summary>
/// Handles the PowerModeChanged event of the SystemEvents control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="PowerModeChangedEventArgs"/> instance containing the event data.</param>
void SystemEvents_PowerModeChanged(object sender, PowerModeChangedEventArgs e)
{
Stop();
Start();
} }
/// <summary> /// <summary>
@ -288,47 +302,14 @@ namespace MediaBrowser.Server.Implementations.IO
/// </summary> /// </summary>
/// <param name="sender">The source of the event.</param> /// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="ErrorEventArgs" /> instance containing the event data.</param> /// <param name="e">The <see cref="ErrorEventArgs" /> instance containing the event data.</param>
async void watcher_Error(object sender, ErrorEventArgs e) void watcher_Error(object sender, ErrorEventArgs e)
{ {
var ex = e.GetException(); var ex = e.GetException();
var dw = (FileSystemWatcher)sender; var dw = (FileSystemWatcher)sender;
Logger.ErrorException("Error in Directory watcher for: " + dw.Path, ex); Logger.ErrorException("Error in Directory watcher for: " + dw.Path, ex);
//Network either dropped or, we are coming out of sleep and it hasn't reconnected yet - wait and retry DisposeWatcher(dw);
var retries = 0;
var success = false;
while (!success && retries < 10)
{
await Task.Delay(500).ConfigureAwait(false);
try
{
dw.EnableRaisingEvents = false;
dw.EnableRaisingEvents = true;
success = true;
}
catch (ObjectDisposedException)
{
RemoveWatcherFromList(dw);
return;
}
catch (IOException)
{
Logger.Warn("Network still unavailable...");
retries++;
}
catch (ApplicationException)
{
Logger.Warn("Network still unavailable...");
retries++;
}
}
if (!success)
{
Logger.Warn("Unable to access network. Giving up.");
DisposeWatcher(dw);
}
} }
/// <summary> /// <summary>
@ -348,7 +329,7 @@ namespace MediaBrowser.Server.Implementations.IO
var nameFromFullPath = Path.GetFileName(e.FullPath); var nameFromFullPath = Path.GetFileName(e.FullPath);
// Ignore certain files // Ignore certain files
if (!string.IsNullOrEmpty(nameFromFullPath) && _alwaysIgnoreFiles.Contains(nameFromFullPath, StringComparer.OrdinalIgnoreCase)) if (!string.IsNullOrEmpty(nameFromFullPath) && _alwaysIgnoreFiles.Contains(nameFromFullPath, StringComparer.OrdinalIgnoreCase))
{ {
return; return;
} }