exception with no stack trace - how?

2019-02-11 18:42发布

We have a service which will log unhandled exceptions at the app domain level (via Log4net).

We logged:

2014-01-28 16:49:19,636 ERROR [49] FeedWrapperService - unhandled System.NullReferenceException: Object reference not set to an instance of an object.

This exception has no stack trace. How is that possible without doing some crazy things to the exception object?

Our handling code:

AppDomain.CurrentDomain.UnhandledException += LogAnyExceptions;

private void LogAnyExceptions(object sender, UnhandledExceptionEventArgs e)
{
    log.Error("unhandled", (Exception)e.ExceptionObject);
    throw (Exception)e.ExceptionObject;
}

It occurs to me that the re-throw here is pointless because the AppDomain will come down along with the process anyway, but I don't think it affects our situation.

The windows application event viewer also shows only this null ref exception and no trace.

I've tested the exception handler logging and it successfully logs the stack trace and any inner exception. If it was thrown by our code, we would see a stack trace. If it was thrown by the 3rd party c# library then, again, we would see a stack trace of at least one method (whether it was a re-thrown exception or not). Here we see a managed exception with no stack trace. I don't know how this is possible.

Looking at the decompiled 3rd party library it talks to unmanaged code, and the event that raised this exception is likely in unmanaged land, but how could such a situation cause a managed null ref exception without a stacktrace?

The cause of this problem is intermittent. We've been running this code in production for several months and seen it do this once. It's pretty freaky.

The general consensus is that the system responsible for this kind of problem should be pushed off into a child process so we can deal with the problem and restart safely and automatically, but it would be nice to know what's going on.

Edit to include comment info from below:

My exception is not a standard re-throw, because the stack trace is either null or empty. It does not have the name of the re-throwing method in it. Digging further, the Exception class can be constructed from serialized info, and it looks like the serialized info could contain null strings for stack trace, and potentially that could be created without causing other errors. I guess it might come from there, but I don't know how it originated.

2条回答
干净又极端
2楼-- · 2019-02-11 19:02

I prefer to manage my exceptions with custom exceptions, If in your case you are using your own exceptions you can go the the class were you define them and override the stacktrace. e.g:

public class YourCustomException: Exception
{
    public YourCustomException() : base() { } //constructor

    public override string StackTrace 
    {
        get { return "Message instead stacktrace"; }
    }
}
查看更多
等我变得足够好
3楼-- · 2019-02-11 19:18

If you're receiving an exception but no corresponding stack trace then at some point an exception handler is probably evaluating the exception and re-throwing it incorrectly. For example, if you're doing a throw ex; you'll eat the stack trace that led to that point. To preserve the existing call stack you want to simply throw; Throwing exceptions best practices

Note that the C# way is the opposite of the convention for the Java language, where you are supposed to throw ex; Java reference: Best Practice: Catching and re-throwing Java Exceptions

查看更多
登录 后发表回答