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