Подтвердить что ты не робот

Исключение без трассировки стека - как?

У нас есть служба, которая будет регистрировать необработанные исключения на уровне домена приложения (через Log4net).

Мы вошли в систему:

2014-01-28 16: 49: 19,636 ОШИБКА [49] FeedWrapperService - необработанный System.NullReferenceException: ссылка на объект не установлена ​​в экземпляр объекта.

В этом исключении нет трассировки стека. Как это возможно без каких-либо сумасшедших вещей для объекта исключения?

Наш код обработки:

AppDomain.CurrentDomain.UnhandledException += LogAnyExceptions;

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

Мне кажется, что повторный бросок здесь бессмыслен, потому что AppDomain все равно будет с ним работать, но я не думаю, что это влияет на нашу ситуацию.

Средство просмотра событий приложения Windows также показывает только это исключение null ref и отсутствие трассировки.

Я проверил ведение журнала обработчиков исключений, и он успешно регистрирует трассировку стека и любое внутреннее исключение. Если бы он был брошен нашим кодом, мы увидели бы трассировку стека. Если он был брошен третьей библиотекой С#, то снова мы увидим трассировку стека хотя бы одного метода (будь то повторное исключение или нет). Здесь мы видим управляемое исключение без трассировки стека. Я не знаю, как это возможно.

Глядя на декомпилированную стороннюю библиотеку, он говорит о неуправляемом коде, и событие, вызвавшее это исключение, скорее всего, находится на неуправляемой земле, но как могла такая ситуация вызвать исключение исключенного исключения без стека?

Причина этой проблемы прерывистая. Мы запускаем этот код в производстве в течение нескольких месяцев и видим, как он это делает. Это довольно странно.

Общий консенсус заключается в том, что система, ответственная за эту проблему, должна быть отброшена в дочерний процесс, чтобы мы могли справиться с проблемой и перезапустить безопасно и автоматически, но было бы хорошо знать, что происходит.

Изменить для включения информации о комментариях ниже:

Мое исключение не является стандартным повторным броском, потому что трассировка стека является пустой или пустой. В нем нет имени метода повторного броска. Копаясь дальше, класс Exception может быть построен из сериализованной информации, и похоже, что сериализованная информация может содержать пустые строки для трассировки стека и потенциально может быть создана без возникновения других ошибок. Я предполагаю, что это может произойти оттуда, но я не знаю, как это произошло.

4b9b3361

Ответ 1

Если вы получаете исключение, но не соответствующую трассировку стека, то в какой-то момент обработчик исключений, вероятно, оценивает исключение и повторно бросает его неправильно. Например, если вы делаете throw ex;, вы будете есть трассировку стека, которая привела бы к этой точке. Чтобы сохранить существующий стек вызовов, вы просто хотите throw; Рекомендации по устранению исключений

Обратите внимание, что путь С# является противоположным соглашению для языка Java, где вы должны throw ex; ссылка на Java: Лучшая практика: Ловля и повторное бросание исключений Java

Ответ 2

Я предпочитаю управлять своими исключениями с пользовательскими исключениями. Если в вашем случае вы используете свои собственные исключения, вы можете пойти в класс, если бы вы определили их и переопределили stacktrace. например:

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

    public override string StackTrace 
    {
        get { return "    at:  my custom stack trace"; }
    }
}