Last active
August 8, 2016 17:48
-
-
Save kumpera/5bd76a981642935bc5ddacdccb6e0d7e to your computer and use it in GitHub Desktop.
This file contains hidden or 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.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