1*fe36f081STimo Kreuzer // Copyright (c) Microsoft. All rights reserved. 2*fe36f081STimo Kreuzer // Licensed under the MIT license. See LICENSE file in the project root for 3*fe36f081STimo Kreuzer // full license information. 4*fe36f081STimo Kreuzer 5*fe36f081STimo Kreuzer /* 6*fe36f081STimo Kreuzer ** The first call to Test checks to make sure that we don't call terminate 7*fe36f081STimo Kreuzer ** when an SEH fault is triggered. After catching the SEH fault, we then 8*fe36f081STimo Kreuzer ** cause a C++ EH fault (where the destructed object is in the try-block 9*fe36f081STimo Kreuzer ** that threw the exception). The C++ EH fault in the dtor should cause 10*fe36f081STimo Kreuzer ** a call to terminate(); in this case, we register our own handler to 11*fe36f081STimo Kreuzer ** trap the call to terminate(). We then run a second C++ EH fault (where 12*fe36f081STimo Kreuzer ** the destructed object is higher in the call tree than where the 13*fe36f081STimo Kreuzer ** exception was thrown). We trap this call to terminate() as well (with 14*fe36f081STimo Kreuzer ** a different handler) and then exit. 15*fe36f081STimo Kreuzer */ 16*fe36f081STimo Kreuzer 17*fe36f081STimo Kreuzer #include <stdio.h> 18*fe36f081STimo Kreuzer #include <stdlib.h> 19*fe36f081STimo Kreuzer #include <eh.h> 20*fe36f081STimo Kreuzer 21*fe36f081STimo Kreuzer int FGenSEHException; 22*fe36f081STimo Kreuzer 23*fe36f081STimo Kreuzer class C 24*fe36f081STimo Kreuzer { 25*fe36f081STimo Kreuzer public: C()26*fe36f081STimo Kreuzer C() {} ~C()27*fe36f081STimo Kreuzer ~C() 28*fe36f081STimo Kreuzer { 29*fe36f081STimo Kreuzer printf( "in C::~C()\n"); 30*fe36f081STimo Kreuzer if (FGenSEHException) 31*fe36f081STimo Kreuzer { 32*fe36f081STimo Kreuzer printf("generating access violation (SEH)\n"); 33*fe36f081STimo Kreuzer *(volatile char*)(0) = 0; // Uh, EHa, don't you think? 34*fe36f081STimo Kreuzer } 35*fe36f081STimo Kreuzer else 36*fe36f081STimo Kreuzer { 37*fe36f081STimo Kreuzer printf("throwing C++ exception\n"); 38*fe36f081STimo Kreuzer throw 'a'; 39*fe36f081STimo Kreuzer } 40*fe36f081STimo Kreuzer } 41*fe36f081STimo Kreuzer }; 42*fe36f081STimo Kreuzer Test()43*fe36f081STimo Kreuzerint Test() 44*fe36f081STimo Kreuzer { 45*fe36f081STimo Kreuzer try 46*fe36f081STimo Kreuzer { 47*fe36f081STimo Kreuzer C c; 48*fe36f081STimo Kreuzer throw 1; 49*fe36f081STimo Kreuzer } 50*fe36f081STimo Kreuzer catch (int) 51*fe36f081STimo Kreuzer { 52*fe36f081STimo Kreuzer printf("Destructor was not invoked \n"); 53*fe36f081STimo Kreuzer } 54*fe36f081STimo Kreuzer catch (char) 55*fe36f081STimo Kreuzer { 56*fe36f081STimo Kreuzer printf("Destructor exited using an exception\n"); 57*fe36f081STimo Kreuzer } 58*fe36f081STimo Kreuzer #if 0 59*fe36f081STimo Kreuzer catch (...) 60*fe36f081STimo Kreuzer { 61*fe36f081STimo Kreuzer printf("Throw caught by wrong handler\n"); 62*fe36f081STimo Kreuzer } 63*fe36f081STimo Kreuzer #endif 64*fe36f081STimo Kreuzer 65*fe36f081STimo Kreuzer printf("terminate() was not called\n"); 66*fe36f081STimo Kreuzer 67*fe36f081STimo Kreuzer return 1; 68*fe36f081STimo Kreuzer } 69*fe36f081STimo Kreuzer Bar(void)70*fe36f081STimo Kreuzervoid Bar(void) 71*fe36f081STimo Kreuzer { 72*fe36f081STimo Kreuzer printf("in %s\n", __FUNCTION__); 73*fe36f081STimo Kreuzer throw 1; 74*fe36f081STimo Kreuzer } 75*fe36f081STimo Kreuzer Test2(void)76*fe36f081STimo Kreuzervoid Test2(void) 77*fe36f081STimo Kreuzer { 78*fe36f081STimo Kreuzer printf("in %s\n", __FUNCTION__); 79*fe36f081STimo Kreuzer C c; 80*fe36f081STimo Kreuzer Bar(); 81*fe36f081STimo Kreuzer return; 82*fe36f081STimo Kreuzer } 83*fe36f081STimo Kreuzer Terminate2(void)84*fe36f081STimo Kreuzervoid __cdecl Terminate2(void) 85*fe36f081STimo Kreuzer { 86*fe36f081STimo Kreuzer printf("termination handler (%s) called\n", __FUNCTION__); 87*fe36f081STimo Kreuzer exit(0); 88*fe36f081STimo Kreuzer } 89*fe36f081STimo Kreuzer Terminate1(void)90*fe36f081STimo Kreuzervoid __cdecl Terminate1(void) 91*fe36f081STimo Kreuzer { 92*fe36f081STimo Kreuzer printf("termination handler (%s) called\n", __FUNCTION__); 93*fe36f081STimo Kreuzer 94*fe36f081STimo Kreuzer // Set a new handler and run a second C++ EH test case. 95*fe36f081STimo Kreuzer set_terminate(Terminate2); 96*fe36f081STimo Kreuzer Test2(); 97*fe36f081STimo Kreuzer exit(0); 98*fe36f081STimo Kreuzer } 99*fe36f081STimo Kreuzer main(void)100*fe36f081STimo Kreuzerint main(void) 101*fe36f081STimo Kreuzer { 102*fe36f081STimo Kreuzer int i; 103*fe36f081STimo Kreuzer 104*fe36f081STimo Kreuzer // First check that we don't terminate on an SEH exception 105*fe36f081STimo Kreuzer FGenSEHException = 1; 106*fe36f081STimo Kreuzer __try 107*fe36f081STimo Kreuzer { 108*fe36f081STimo Kreuzer i = Test(); 109*fe36f081STimo Kreuzer } 110*fe36f081STimo Kreuzer __except (1) 111*fe36f081STimo Kreuzer { 112*fe36f081STimo Kreuzer printf("caught SEH exception in %s\n", __FUNCTION__); 113*fe36f081STimo Kreuzer } 114*fe36f081STimo Kreuzer 115*fe36f081STimo Kreuzer // Now set our own terminate handler and throw a C++ EH exception 116*fe36f081STimo Kreuzer set_terminate(Terminate1); 117*fe36f081STimo Kreuzer FGenSEHException = 0; 118*fe36f081STimo Kreuzer i = Test(); 119*fe36f081STimo Kreuzer 120*fe36f081STimo Kreuzer // Should never get here 121*fe36f081STimo Kreuzer printf("termination handler not called\n"); 122*fe36f081STimo Kreuzer return i; 123*fe36f081STimo Kreuzer } 124