October 13, 2011

Crash IIS event 5011 and how to add your unhandled exceptions in the event viewer

Recently I had a bug in one of my website because of a recursive infinite loop. The effect was some random restart of IIS but noting in the sitecore logs and not way to know why.

In the windows event viewer I saw in the IIS section that the I had some IIS crashes with the event code 5011.

After googling a little bit I found this website: http://martinnormark.com/how-to-handle-iis-event-id-1009-event-id-5011-on-iis-7

So, if you create a dll with this class

#region Using

using System;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Web;

#endregion

/// <summary>
/// Handles all unhandled exceptions from in the current AppDomain. 
/// 
/// Works great to catch unhandled exceptions thrown by IIS's child threads, /// which will make the application pool terminate unexpectedly 

/// without logging. This makes sure your Exception /// is logged to the Application event log.
/// </summary>
public class UnhandledExceptionModule : IHttpModule
{
  #region Fields

  private static int _UnhandledExceptionCount = 0;
  private static string _SourceName = null;
  private static object _InitLock = new object();
  private static bool _Initialized = false;

  #endregion

  #region IHttpModule members

  public void Init(HttpApplication app)
  {

    // Do this one time for each AppDomain.
    if (!_Initialized)
    {
      lock (_InitLock)
      {
        if (!_Initialized)
        {
          string webenginePath = Path.Combine(RuntimeEnvironment.GetRuntimeDirectory(), "webengine.dll");

          if (!File.Exists(webenginePath))
          {
            throw new Exception(String.Format(CultureInfo.InvariantCulture,                 "Failed to locate webengine.dll at '{0}'.  This module requires .NET Framework 2.0.", webenginePath));
          }

          FileVersionInfo ver = FileVersionInfo.GetVersionInfo(webenginePath);
          _SourceName = string.Format(CultureInfo.InvariantCulture, "ASP.NET {0}.{1}.{2}.0", ver.FileMajorPart,                 ver.FileMinorPart, ver.FileBuildPart);

          if (!EventLog.SourceExists(_SourceName))
          {
            throw new Exception(String.Format(CultureInfo.InvariantCulture,                 "There is no EventLog source named '{0}'. This module requires .NET Framework 2.0.", _SourceName));
          }

          AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(OnUnhandledException);

          _Initialized = true;
        }
      }
    }
  }

  public void Dispose()
  {
  }

  #endregion

  #region UnhandledException event handler

  public void OnUnhandledException(object o, UnhandledExceptionEventArgs e)
  {
    // Let this occur one time for each AppDomain.
    if (Interlocked.Exchange(ref _UnhandledExceptionCount, 1) != 0)
      return;

    StringBuilder message = new StringBuilder("\r\n\r\nUnhandledException logged by UnhandledExceptionModule:\r\n\r\nappId=");

    string appId = (string)AppDomain.CurrentDomain.GetData(".appId");
    if (appId != null)
    {
      message.Append(appId);
    }

    Exception currentException = null;
    for (currentException = (Exception)e.ExceptionObject; currentException != null; currentException = currentException.InnerException)
    {
      message.AppendFormat("\r\n\r\ntype={0}\r\n\r\nmessage={1}\r\n\r\nstack=\r\n{2}\r\n\r\n",
                           currentException.GetType().FullName,
                           currentException.Message,
                           currentException.StackTrace);
    }

    EventLog Log = new EventLog();
    Log.Source = _SourceName;
    Log.WriteEntry(message.ToString(), EventLogEntryType.Error);
  }

  #endregion
}

Add add this
<httpmodules>            
    <add name="UnhandledExceptionModule" type="UnhandledExceptionModule"/>        
    .....
</httpmodules>

You will have more details about the cause of this error a StackOverflowException in my case.

It takes me a lot of time to find why because I didn't find how to know witch line or class cause the exception but it already help a lot :)

This class also adds all the unhandled error in the event viewer so it is also great to have it.

1 comment: