Skip to content

Commit

Permalink
handling exceptions from FileWatcherEventSource
Browse files Browse the repository at this point in the history
  • Loading branch information
brettsam committed Feb 12, 2018
1 parent 482deff commit 19171d6
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 3 deletions.
15 changes: 13 additions & 2 deletions src/WebJobs.Script/Eventing/File/FileWatcherEventSource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ public sealed class FileWatcherEventSource : IDisposable
private readonly AutoRecoveringFileSystemWatcher _fileWatcher;
private readonly IScriptEventManager _eventManager;
private readonly string _source;
private readonly TraceWriter _traceWriter;
private bool _disposed = false;

public FileWatcherEventSource(IScriptEventManager eventManager,
Expand All @@ -27,12 +28,22 @@ public FileWatcherEventSource(IScriptEventManager eventManager,
_eventManager = eventManager;
_fileWatcher = new AutoRecoveringFileSystemWatcher(path, filter, includeSubdirectories, changeTypes, traceWriter);
_fileWatcher.Changed += FileChanged;
_traceWriter = traceWriter;
}

private void FileChanged(object sender, FileSystemEventArgs e)
{
var fileEvent = new FileEvent(_source, e);
_eventManager.Publish(fileEvent);
// This handler is called on a background thread, so any exceptions thrown will crash
// the process. Handle and log all errors instead.
try
{
var fileEvent = new FileEvent(_source, e);
_eventManager.Publish(fileEvent);
}
catch (Exception ex)
{
_traceWriter?.Error($"Error handling '{e.ChangeType}' notification for '{e.FullPath}'.", ex);
}
}

private void Dispose(bool disposing)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reactive.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Azure.WebJobs.Script.Eventing;
using Microsoft.Azure.WebJobs.Script.Eventing.File;
Expand Down Expand Up @@ -66,5 +66,29 @@ public async Task DisposedSource_DoesNotPublishEvents()
Assert.Equal(2, events.Count);
}
}

[Fact]
public async Task FileChangedHandlerExceptions_LogError_AndDoNotThrow()
{
// Note: The FileSystemWatcher handler is called on a background thread. This means that when the handler
// throws an exception, it crashes the process. The Visual Studio test runner handles that scenario and
// does not crash. Before this handler was fixed, this test would only fail in the console runner.

TestTraceWriter traceWriter = new TestTraceWriter(TraceLevel.Verbose);
using (var directory = new TempDirectory())
using (var eventManager = new ScriptEventManager())
using (var eventSource = new FileWatcherEventSource(eventManager, "TestSource", directory.Path, traceWriter: traceWriter))
{
var expectedException = new InvalidOperationException("This should not crash the process!");
eventManager.Subscribe(p => throw expectedException);

string fullPath = Path.Combine(directory.Path, "test.txt");
File.WriteAllText(fullPath, "Test");

await TestHelpers.Await(
() => traceWriter.GetTraces().Any(p => p.Level == TraceLevel.Error && p.Message.Contains(fullPath) && p.Exception == expectedException),
timeout: 2000, pollingInterval: 250);
}
}
}
}

0 comments on commit 19171d6

Please sign in to comment.