Skip to content

Instantly share code, notes, and snippets.

@kumpera
Last active August 8, 2016 17:48
Show Gist options
  • Select an option

  • Save kumpera/5bd76a981642935bc5ddacdccb6e0d7e to your computer and use it in GitHub Desktop.

Select an option

Save kumpera/5bd76a981642935bc5ddacdccb6e0d7e to your computer and use it in GitHub Desktop.
using System;
using System.Threading;
using System.Runtime.CompilerServices;
class Driver
{
public static ManualResetEvent mre1 = new ManualResetEvent (false);
public static ManualResetEvent mre2 = new ManualResetEvent (false);
class StaticConstructor1
{
internal static bool gotToEnd, caughtException;
static StaticConstructor1 ()
{
try {
Console.WriteLine ("StaticConstructor1.StaticConstructor1 (1)");
Driver.mre1.Set ();
Thread.Sleep (1000);
Console.WriteLine ("StaticConstructor1.StaticConstructor1 (2)");
gotToEnd = true;
} catch (Exception e) {
caughtException = true;
throw;
}
}
public static void Init ()
{
Console.WriteLine ("StaticConstructor1.Init");
}
}
[MethodImplAttribute (MethodImplOptions.NoInlining)]
static void IsStaticConstructor1Viable () {
new StaticConstructor1 ();
Console.WriteLine ("Did it get to the end? {0} Did it catch an exception {1}", StaticConstructor1.gotToEnd, StaticConstructor1.caughtException);
if (!StaticConstructor1.gotToEnd) /* the TAE must not land during a .cctor */
Environment.Exit (1);
if (StaticConstructor1.caughtException)
Environment.Exit (1);
}
static void Test1 ()
{
Console.WriteLine ("Test 1:");
Driver.mre1.Reset ();
Driver.mre2.Reset ();
Thread thread = new Thread (() => {
try {
StaticConstructor1.Init ();
} catch (Exception e) {
Console.WriteLine ("StaticConstructor1::init caught exception {0}", e);
if (!(e is ThreadAbortException))
throw;
}
});
thread.Start ();
Driver.mre1.WaitOne ();
// The ThreadAbortException should land while in
// the StaticConstructor1.cctor. The exception should
// be queued, and be rethrown when exiting the cctor.
thread.Abort ();
thread.Join ();
//is StaticConstructor1 viable?
try {
IsStaticConstructor1Viable ();
Console.WriteLine ("StaticConstructor1 is viable"); /* a TAE doesn't make a type unusable */
} catch (TypeInitializationException e) {
Console.WriteLine ("StaticConstructor1 not viable");
Environment.Exit (1);
}
}
class StaticConstructor2Exception : Exception {}
class StaticConstructor2
{
static StaticConstructor2 ()
{
Console.WriteLine ("StaticConstructor2.StaticConstructor2 (1)");
Driver.mre1.Set ();
throw new StaticConstructor2Exception ();
/* Unreachable */
Driver.mre2.Set ();
Console.WriteLine ("StaticConstructor2.StaticConstructor2 (2)");
}
public static void Init ()
{
Console.WriteLine ("StaticConstructor2.Init");
}
}
[MethodImplAttribute (MethodImplOptions.NoInlining)]
static void IsStaticConstructor2Viable () {
new StaticConstructor2 ();
}
static void Test2 ()
{
Console.WriteLine ("Test 2:");
Driver.mre1.Reset ();
Driver.mre2.Reset ();
Thread thread = new Thread (() => {
try {
StaticConstructor2.Init ();
} catch (TypeInitializationException e) {
Console.WriteLine (e);
if (!(e.InnerException is StaticConstructor2Exception))
throw;
}
});
thread.Start ();
Driver.mre1.WaitOne ();
// A InvalidOperationException should be thrown while in
// the StaticConstructor2.cctor. The exception should
// be wrapped in a TypeInitializationException.
if (Driver.mre2.WaitOne (500)) {
/* We shouldn't reach Driver.mre.Set () in StaticConstructor2.cctor */
Environment.Exit (1);
}
thread.Join ();
//is StaticConstructor2 viable?
try {
IsStaticConstructor2Viable ();
Console.WriteLine ("StaticConstructor2 is viable");
/* A regular exception escaping the .cctor makes the type not usable */
Environment.Exit (1);
} catch (TypeInitializationException e) {
Console.WriteLine ("StaticConstructor2 not viable");
}
}
public static void Main ()
{
Test1 ();
Test2 ();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment