Reputation: 28312
The application I've been working on has recently started experiencing intermittent hard crashes which I'm unable to explain. To make this more weird we have both AppDomain.CurrentDomain.UnhandledException
and TaskScheduler.UnobservedTaskException
set up to catch problems like these.
Usually when something goes wrong the above two work correctly, but we have certain circumstances where they are not catching unhandled exceptions. To make matters even worse the exception that's causing this is a NRE which means we have nothing to go on in terms of tracking down what's going on.
My first thought was that maybe the code we have in the unhandled exception handlers might be throwing exceptions, so we doubled down on exception handling here, but so far that hasn't made any difference. The logs we have also haven't been able to shine any light on this.
This may be a bug with webapi and/or the owin bits we are using to host the application, and I'm going to try bumping the dependencies to see if that helps, but I don't think it will make any difference.
Is there a way to trap unhandled exceptions occurring in the thread pool? Is there some kind of diagnostics we can enable to get more info as to where this is happening?
I'm at my wits end, any help would be greatly appreciated.
System.NullReferenceException: Object reference not set to an instance of an object.
at System.Net.HttpListener.EndGetContext(IAsyncResult asyncResult)
at System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endFunction, Action`1 endAction, Task`1 promise, Boolean requiresSynchronization)
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at Microsoft.Owin.Host.HttpListener.OwinHttpListener.<ProcessRequestsAsync>d__0.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.<ThrowAsync>b__5(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
at System.Threading.ThreadPoolWorkQueue.Dispatch()
When using tasks we do not do async void
, but we have one case of Task.Run
where we do not await or hang on the task. This is:
Task.Run(() => CleanUpAllExpiredErrors());
This method cleans up expired client errors (we capture client side stack traces on unhandled client errors).
Upvotes: 4
Views: 825
Reputation: 28312
By adding extensive tracing and logging we saw that this crash was consistently happening when serving static assets, specifically stylesheets. We white-listed our static assets directories to not require authentication and the crash went away.
We configure certain endpoints to not require authentication by doing the following:
var listener = (HttpListener)app.Properties["System.Net.HttpListener"];
listener.AuthenticationSchemeSelectorDelegate = request =>
{
// Options requests should always be anonymous otherwise preflight cors requests
// will fail in Firefox.
if (request.HttpMethod == "OPTIONS")
{
return AuthenticationSchemes.Anonymous;
}
// here we add additional whitelisted paths
var pathsWithoutAuthentication = KnownPaths.AnonymousWhiteList.Concat(KnownPaths.Assets);
return pathsWithoutAuthentication.Any(a => request.RawUrl.ToLower().StartsWith(a))
? AuthenticationSchemes.Anonymous
: AuthenticationSchemes.IntegratedWindowsAuthentication;
};
Upvotes: 3