Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Elmah throws ObjectDisposedException

I have an MVC app running on IIS 7 using windows authentication and Elmah logging.

Normally when an error happens, we call something like "logger.LogError" which is a wrapper for:

Elmah.ErrorLog.GetDefault(null).Log(new Elmah.Error(new Exception(message)));

We have a remote system set up to run jobs that pings the web application periodically, in order to wake it up and tell it to run a specific job. The remote application uses HttpClient::GetAsync(...) to connect to the site.

The page that the remote ping hits, executes the job it needs to run in a thread but does not await, since we want the ping to respond immediately. Unfortunately, this has the added drawback of breaking the Elmah logging.

If we have any kind of logged error occur during the job execution, when we get to the "LogError" method, Elmah throws an "ObjectDisposedException" with the message "Safe Handle has been closed" (probably bubbled up from trying to access the current users identity). I checked in the watch window while debugging, and the part that is throwing the error is:

new Elmah.Error(new Exception(message))

if I call just "new Elmah.Error()" it works fine, and "new Exception(message)" also works fine, but when passing an exception as the parameter to the error constructor, that's when it fails. Also, I cannot assign an exception after creating a new error object, as the property is read-only.

I'm pretty sure that it's because the current windows identity has gone out of scope in the parent thread when it finishes. Is there any way of getting around this issue without resorting to an await on the job execution? The problem is that the jobs can take a very long time to run, and we don't want the remote ping app to either timeout or hang for a long time while waiting for a response.

like image 640
Code Monkey Avatar asked Aug 31 '26 06:08

Code Monkey


1 Answers

In case someone else runs across this, here's what I ended up doing:

In a situation where you'd normally call

Elmah.ErrorSignal.FromCurrentContext().Raise(ex);

Call this function instead:

public static void LogError(Exception ex)
    {
        if (HttpContext.Current == null)
        {
            var errorlog = Elmah.ErrorLog.GetDefault(null);
            var error = new Elmah.Error();
            error.Message = ex.Message;
            error.Detail = ex.ToString();
            error.Time = DateTime.Now;
            error.Type = ex.GetType() + "[NoContext]";
            error.HostName = Environment.MachineName;
            errorlog.Log(error);
        } else {
            Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
        }
    }

Caveats apply:

  • All this does is log to your default log. It won't send e-mail or do any of the other fancy things Elmah can do with an HttpContext
  • You won't get the full yellow screen of death - just the ToString() representation of the exception, which is less useful.
like image 140
Dave Avatar answered Sep 01 '26 21:09

Dave



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!