Skip to content

Instantly share code, notes, and snippets.

@Upliner
Created November 25, 2016 15:08
Show Gist options
  • Save Upliner/8b2da2beb7ae5da0e659a88255ea750e to your computer and use it in GitHub Desktop.
Save Upliner/8b2da2beb7ae5da0e659a88255ea750e to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.Threading;
namespace MyCoolProject
{
/**<summary>
* Fact of existence of this exception causes immediate termination.
* </summary>
* <remarks>
* It is not an exception in the full sense of word, it is just more reliable and convenient alternative for
* "<c>Environment.FailFast()</c>". The syntax "<c>throw new CatastrophicException()</c>" just indicates for compiler that
* code after it is unreachable so it wouldn't check the uninitialized variables, etc. whereas application is terminated
* by <c>CatastrophicException</c>'s constructor, not the <c>throw</c> statement!
* </list>
* </remarks>
*/
internal sealed class CatastrophicException: /*NoCatch*/Exception
{
private static bool corpse = false;
/**<summary>
* Don't try to do anything if you are already a corpse!!!
* <para>Use this property ONLY to help <c>CatastrophicException</c> terminate the application.</para>
* </summary>
* <remarks>
* Only appropriate usage for this property:
* <code>if (CatastrophicException.Corpse) throw new CatastrophicException();</code>
* OR terminate the application by any other way to avoid interrupting a more sensitive code.
* <para>
* DO NOT use this property for saving data, flushing buffers and so on. This may cause a catastrophic damage!
* If something savable survived in this situation, save it BEFORE throwing <c>CatastrophicException</c>!
* After throwing it there a no longer anything savable left. Use this property ONLY for termination!
* </para>
* <para>Anyway, there are really small chance for application for survive after throwing
* <c>CatastrophicException</c>, so please do all finalization before throwing instead of catching or checking a
* Corpse property. But for full guarantee you can check Corpse property to prevent sensitive code from executing by
* dead application and terminate it immediately.</para>
* </remarks>
* <seealso cref="T:MyCoolProject.CatastrophicException"/>
*/
public static bool Corpse { get { return corpse; } }
private /*noreturn*/ void DIE()
{
try
{
Environment.FailFast("Catastrophic Exception!!!");
} finally //Wouldn't execute if FailFast will succeed
{
try
{
Environment.Exit(-1);
} catch { }
try
{
RecurseDeath();
} finally
{
throw this;//If we don't have a permission for immediate exit, throw CatastrophicException down
//this is the best way for quick termination because any operation (even destuction during garbage collection) with CatastrophicException object will rethrow it
}
}
}
/// <summary>
/// Kill the application. It will be killed even if you don't throw constructed exception.
/// </summary>
public CatastrophicException()
{
corpse = true; //you will become a corpse after creating a first instance... not zombie, just a corpse mechanically flying forward!!!
DIE();
}
public sealed override string ToString()
{
DIE();
throw this;//to shut up a "must return a value" compiler error. DIE() is noreturn anyway
}
public sealed override System.Collections.IDictionary Data
{
get
{
DIE();
throw this;
}
}
public sealed override bool Equals(object obj)
{
DIE();
throw this;
}
public sealed override Exception GetBaseException()
{
DIE();
throw this;
}
public sealed override int GetHashCode()
{
DIE();
throw this;
}
public sealed override string HelpLink
{
get
{
DIE();
throw this;
}
set
{
DIE();
}
}
public sealed override string Message
{
get
{
DIE();
throw this;
}
}
public sealed override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context)
{
DIE();
}
public sealed override string Source
{
get
{
DIE();
throw this;
}
set
{
DIE();
}
}
public sealed override string StackTrace
{
get
{
DIE();
throw this;
}
}
/// <summary>Recursive application killer!!!</summary>
void RecurseDeath()
{
try
{
RecurseDeath();
} finally
{
RecurseDeath();
}
}
///<summary>
///Even if CatastrophicException was caught and not rethrown, application will be killed on next garbage collection
///<para>Calling this finalizer causing segfault on .NET Framework 2.0.</para>
///</summary>
~CatastrophicException()
{
try
{
GC.ReRegisterForFinalize(this);
GC.ReRegisterForFinalize(this);
RecurseDeath();
} finally
{
//start the chain reaction until program will be destroyed
for (int i = 0; i < 20; i++)//We need some "critical mass"
{
try
{
new CatastrophicException().DIE();
} catch { }
}
RecurseDeath();
try
{
GC.Collect();
GC.WaitForPendingFinalizers();
} finally
{
try
{
DIE();
} finally
{
GC.ReRegisterForFinalize(this);
GC.ReRegisterForFinalize(this);
GC.Collect();
GC.WaitForPendingFinalizers();
}
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment