Critical exceptions are exceptions that should not be caught. In C#, exceptions that indicate a catastrophic failure of the runtime or the process are generally known as Corrupted State Exceptions (CSEs). You should avoid catching these because the state of the application is no longer predictable, and attempting to execute code—especially code that allocates memory for logging—can lead to secondary crashes or hang the process.
public static class ExceptionExtender
{
/*
The primary exceptions you should avoid catching in a general exception handler are:
Exception Reason
OutOfMemoryException Logging/documenting the exception may itself fail due to lack of available memory.
StackOverflowException The stack is already exhausted; attempting to execute logging code will fail.
ExecutionEngineException Represents a critical CLR failure; recovery is not guaranteed. OBSOLETE now.
AccessViolationException Indicates unsafe memory access; logging may be unsafe or unreliable.
ThreadAbortException Thrown by the runtime to abort a thread; catching and rethrowing can interfere with CLR cleanup.
AppDomainUnloadedException The application domain is being unloaded; recovery is not possible.
BadImageFormatException Indicates a corrupted or invalid assembly; recovery is not feasible.
*/
public static bool IsCriticalException(this Exception ex)
{
return ex is OutOfMemoryException or
StackOverflowException or
// ExecutionEngineException or // OBSOLETE: ExecutionEngineException is obsolete and should not be used in new code. It was used to indicate a severe error in the execution engine of the .NET runtime, but it has been deprecated and is no longer relevant in modern .NET applications.
AccessViolationException or
ThreadAbortException or
AppDomainUnloadedException or
BadImageFormatException;
}
}
Here is an example for using it:
public T? LoadFromJsonFile(string jsonFilePath) where T : class, new()
{
Debug.Assert(jsonFilePath != null, $"Parameter {nameof(jsonFilePath)} is null");
T? reconstituted = null;
try
{
using (var stream = _fileSystem.File.OpenRead(jsonFilePath))
{
reconstituted = JsonSerializer.Deserialize(stream, _serializerOptions);
}
}
catch (Exception ex) when (!ex.IsCriticalException())
{
_logger.Log(LogLevel.Error, CallerContext.Create(), "Exception deserializing JSON from file '{JsonFilePath}' of: {Exception}",
jsonFilePath, ex);
}
return reconstituted;
}
No comments:
Post a Comment