1 using System;
2 using System.Diagnostics;
3 using System.Threading;
4 using System.Runtime.CompilerServices;
5 
6 class Driver
7 {
8 	public static ManualResetEvent mre1 = new ManualResetEvent (false);
9 	public static ManualResetEvent mre2 = new ManualResetEvent (false);
10 
11 	class StaticConstructor1
12 	{
13 		internal static bool gotToEnd, caughtException;
StaticConstructor1()14 		static StaticConstructor1 ()
15 		{
16 			try {
17 				Console.WriteLine ("StaticConstructor1.StaticConstructor1 (1)");
18 				Driver.mre1.Set ();
19 				var sw = Stopwatch.StartNew ();
20 				Thread.Sleep (1000);
21 				sw.Stop ();
22 				typeof (string).GetMethods ();
23 				//XXX we assume that if we slept less than 900ms we got aborted
24 				if (sw.ElapsedMilliseconds < 900)
25 					throw new Exception ("Bad abort broke our sleep");
26 				Console.WriteLine ("StaticConstructor1.StaticConstructor1 (2) waited {0}", sw.ElapsedMilliseconds);
27 				gotToEnd = true;
28 			} catch (Exception e) {
29 				caughtException = true;
30 				throw;
31 			}
32 		}
33 
Init()34 		public static void Init ()
35 		{
36 			Console.WriteLine ("StaticConstructor1.Init");
37 		}
38 	}
39 
40 	[MethodImplAttribute (MethodImplOptions.NoInlining)]
IsStaticConstructor1Viable()41 	static void IsStaticConstructor1Viable () {
42 		new StaticConstructor1 ();
43 		Console.WriteLine ("Did it get to the end? {0} Did it catch an exception {1}", StaticConstructor1.gotToEnd, StaticConstructor1.caughtException);
44 		if (!StaticConstructor1.gotToEnd) /* the TAE must not land during a .cctor */
45 			Environment.Exit (1);
46 		if (StaticConstructor1.caughtException)
47 			Environment.Exit (2);
48 
49 	}
50 
Test1()51 	static void Test1 ()
52 	{
53 		Console.WriteLine ("Test 1:");
54 
55 		Driver.mre1.Reset ();
56 		Driver.mre2.Reset ();
57 
58 		Thread thread = new Thread (() => {
59 			try {
60 				StaticConstructor1.Init ();
61 			} catch (Exception e) {
62 				Console.WriteLine ("StaticConstructor1::init caught exception {0}", e);
63 
64 				if (!(e is ThreadAbortException))
65 					throw;
66 			}
67 		});
68 
69 		thread.Start ();
70 
71 		Driver.mre1.WaitOne ();
72 
73 		// The ThreadAbortException should land while in
74 		// the StaticConstructor1.cctor. The exception should
75 		// be queued, and be rethrown when exiting the cctor.
76 		thread.Abort ();
77 
78 		thread.Join ();
79 
80 		//is StaticConstructor1 viable?
81 		try {
82 			IsStaticConstructor1Viable ();
83 			Console.WriteLine ("StaticConstructor1 is viable"); /* a TAE doesn't make a type unusable */
84 		} catch (TypeInitializationException  e) {
85 			Console.WriteLine ("StaticConstructor1 not viable");
86 			Environment.Exit (3);
87 		}
88 	}
89 
90 	class StaticConstructor2Exception : Exception {}
91 
92 	class StaticConstructor2
93 	{
StaticConstructor2()94 		static StaticConstructor2 ()
95 		{
96 			Console.WriteLine ("StaticConstructor2.StaticConstructor2 (1)");
97 			Driver.mre1.Set ();
98 			throw new StaticConstructor2Exception ();
99 			/* Unreachable */
100 			Driver.mre2.Set ();
101 			Console.WriteLine ("StaticConstructor2.StaticConstructor2 (2)");
102 		}
103 
Init()104 		public static void Init ()
105 		{
106 			Console.WriteLine ("StaticConstructor2.Init");
107 		}
108 	}
109 
110 	[MethodImplAttribute (MethodImplOptions.NoInlining)]
IsStaticConstructor2Viable()111 	static void IsStaticConstructor2Viable () {
112 		new StaticConstructor2 ();
113 	}
114 
115 
Test2()116 	static void Test2 ()
117 	{
118 		Console.WriteLine ("Test 2:");
119 
120 		Driver.mre1.Reset ();
121 		Driver.mre2.Reset ();
122 
123 		Thread thread = new Thread (() => {
124 			try {
125 				StaticConstructor2.Init ();
126 			} catch (TypeInitializationException e) {
127 				Console.WriteLine (e);
128 
129 				if (!(e.InnerException is StaticConstructor2Exception))
130 					throw;
131 			}
132 		});
133 
134 		thread.Start ();
135 
136 		Driver.mre1.WaitOne ();
137 
138 		// A InvalidOperationException should be thrown while in
139 		// the StaticConstructor2.cctor. The exception should
140 		// be wrapped in a TypeInitializationException.
141 
142 		if (Driver.mre2.WaitOne (500)) {
143 			/* We shouldn't reach Driver.mre.Set () in StaticConstructor2.cctor */
144 			Environment.Exit (4);
145 		}
146 
147 		thread.Join ();
148 
149 		//is StaticConstructor2 viable?
150 		try {
151 			IsStaticConstructor2Viable ();
152 			Console.WriteLine ("StaticConstructor2 is viable");
153 			/* A regular exception escaping the .cctor makes the type not usable */
154 			Environment.Exit (5);
155 		} catch (TypeInitializationException e) {
156 			Console.WriteLine ("StaticConstructor2 not viable");
157 		}
158 
159 	}
160 
161 	class StaticConstructor3
162 	{
StaticConstructor3()163 		static StaticConstructor3 ()
164 		{
165 			Console.WriteLine ("StaticConstructor3.StaticConstructor3 (1)");
166 			Driver.mre1.Set ();
167 			Thread.CurrentThread.Abort ();
168 			/* Unreachable */
169 			Driver.mre2.Set ();
170 			Console.WriteLine ("StaticConstructor3.StaticConstructor3 (2)");
171 			Environment.Exit (6);
172 		}
173 
Init()174 		public static void Init ()
175 		{
176 			Console.WriteLine ("StaticConstructor3.Init");
177 		}
178 	}
179 
180 	[MethodImplAttribute (MethodImplOptions.NoInlining)]
IsStaticConstructor3Viable()181 	static void IsStaticConstructor3Viable () {
182 		new StaticConstructor3 ();
183 	}
184 
Test3()185 	static void Test3 ()
186 	{
187 		Console.WriteLine ("Test 3:");
188 		bool catched_abort = false;
189 
190 		Driver.mre1.Reset ();
191 		Driver.mre2.Reset ();
192 
193 		Thread thread = new Thread (() => {
194 			try {
195 				StaticConstructor3.Init ();
196 				Console.WriteLine ("cctor3 didn't throw?!?!");
197 				/* StaticConstructor3 self aborted */
198 				Environment.Exit (7);
199 			} catch (ThreadAbortException e) {
200 				Console.WriteLine ("TEST 3: aborted {0}", e);
201 				catched_abort = true;
202 			}
203 		});
204 
205 		thread.Start ();
206 
207 		Driver.mre1.WaitOne ();
208 
209 		// A InvalidOperationException should be thrown while in
210 		// the StaticConstructor2.cctor. The exception should
211 		// be wrapped in a TypeInitializationException.
212 
213 		thread.Join ();
214 
215 		// Did we catch the abort
216 		if (!catched_abort)
217 			Environment.Exit (8);
218 
219 		//is StaticConstructor2 viable?
220 		try {
221 			IsStaticConstructor3Viable ();
222 			Console.WriteLine ("StaticConstructor3 is viable");
223 			/* A regular exception escaping the .cctor makes the type not usable */
224 			Environment.Exit (9);
225 		} catch (TypeInitializationException e) {
226 			Console.WriteLine ("StaticConstructor3 not viable");
227 		}
228 	}
229 
230 
231 
232 
233 
234 	class StaticConstructor4
235 	{
236 		internal static bool gotToEnd, caughtException;
237 
StaticConstructor4()238 		static StaticConstructor4 ()
239 		{
240 			try {
241 				Console.WriteLine ("StaticConstructor4.StaticConstructor4 (1)");
242 				Driver.mre1.Set ();
243 				var sw = Stopwatch.StartNew ();
244 				Thread.Sleep (1000);
245 				sw.Stop ();
246 				typeof (string).GetMethods ();
247 				//XXX we assume that if we slept less than 900ms we got aborted
248 				if (sw.ElapsedMilliseconds < 900)
249 					throw new Exception ("Bad abort broke our sleep");
250 				Console.WriteLine ("StaticConstructor4.StaticConstructor4 (2) waited {0}", sw.ElapsedMilliseconds);
251 				gotToEnd = true;
252 			} catch (Exception e) {
253 				caughtException = true;
254 				throw;
255 			}
256 		}
257 
Init()258 		public static void Init ()
259 		{
260 			Console.WriteLine ("StaticConstructor4.Init");
261 		}
262 	}
263 
264 	static bool got_to_the_end_of_the_finally = false;
265 
266 	[MethodImplAttribute (MethodImplOptions.NoInlining)]
IsStaticConstructor4Viable()267 	static void IsStaticConstructor4Viable () {
268 		new StaticConstructor4 ();
269 		Console.WriteLine ("IsStaticConstructor4Viable: Did it get to the end? {0} Did it catch an exception {1} and end of the finally block {2}", StaticConstructor4.gotToEnd, StaticConstructor4.caughtException, got_to_the_end_of_the_finally);
270 		if (!StaticConstructor4.gotToEnd) /* the TAE must not land during a .cctor */
271 			Environment.Exit (10);
272 		if (StaticConstructor4.caughtException)
273 			Environment.Exit (11);
274 	}
275 
Test4()276 	static void Test4 ()
277 	{
278 		Console.WriteLine ("Test 4:");
279 
280 		Driver.mre1.Reset ();
281 		Driver.mre2.Reset ();
282 
283 		Thread thread = new Thread (() => {
284 			try {
285 
286 				try {
287 				} finally {
288 					StaticConstructor4.Init ();
289 					Console.WriteLine ("Test 4: After the cctor");
290 					got_to_the_end_of_the_finally = true;
291 				}
292 			} catch (Exception e) {
293 				Console.WriteLine ("StaticConstructor4::init caught exception {0}", e);
294 				if (!(e is ThreadAbortException))
295 					throw;
296 				if (!got_to_the_end_of_the_finally)
297 					throw new Exception ("Test 4: did not get to the end of the cctor");
298 			}
299 		});
300 
301 		thread.Start ();
302 
303 		Driver.mre1.WaitOne ();
304 
305 		// The ThreadAbortException should land while in
306 		// the StaticConstructor4.cctor. The exception should
307 		// be queued, and be rethrown when exiting the cctor.
308 		thread.Abort ();
309 
310 		thread.Join ();
311 
312 		if (!got_to_the_end_of_the_finally) {
313 			Console.WriteLine ("Did not get to the end of test 4 cctor");
314 			Environment.Exit (12);
315 		}
316 
317 		//is StaticConstructor4viable?
318 		try {
319 			IsStaticConstructor4Viable ();
320 			Console.WriteLine ("StaticConstructor4 is viable"); /* a TAE doesn't make a type unusable */
321 		} catch (TypeInitializationException  e) {
322 			Console.WriteLine ("StaticConstructor4 not viable");
323 			Environment.Exit (13);
324 		}
325 	}
326 
327 
328 	class StaticConstructor5 {
329 		public static bool catched_exception = false;
StaticConstructor5()330 		static StaticConstructor5 ()
331 		{
332 			Driver.mre1.Set ();
333 			Driver.mre2.WaitOne ();
334 			try {
335 				throw new Exception ();
336 			} catch (Exception) {
337 				Console.WriteLine ("Catched exception in cctor");
338 				catched_exception = true;
339 			}
340 		}
341 	}
342 
Test5()343 	static void Test5 ()
344 	{
345 		bool catched_abort = false;
346 		Driver.mre1.Reset ();
347 		Driver.mre2.Reset ();
348 		Thread thread = new Thread (() => {
349 					try {
350 						new StaticConstructor5 ();
351 					} catch (ThreadAbortException) {
352 						Console.WriteLine ("Catched thread abort");
353 						catched_abort = true;
354 					}
355 				});
356 		thread.Start ();
357 
358 		Driver.mre1.WaitOne ();
359 		thread.Abort ();
360 		Driver.mre2.Set ();
361 
362 		thread.Join ();
363 
364 		if (!StaticConstructor5.catched_exception)
365 			Environment.Exit (14);
366 		if (!catched_abort)
367 			Environment.Exit (15);
368 	}
369 
Main()370 	public static int Main ()
371 	{
372 		Test1 ();
373 		Test2 ();
374 		Test3 ();
375 		Test4 ();
376 		Test5 ();
377 		Console.WriteLine ("done, all things good");
378 		return 0;
379 	}
380 }
381