Created
November 25, 2016 15:08
-
-
Save Upliner/8b2da2beb7ae5da0e659a88255ea750e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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