Changeset 55 for trunk/src/helpers/except.c
- Timestamp:
- Apr 6, 2001, 7:12:11 PM (24 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/helpers/except.c
r32 r55 16 16 * especially applies to multi-thread programs using 17 17 * mutex semaphores (more on that below). The functions 18 * and macros in here are designed to make that more simple. 19 * 20 * The macros in except.h automatically insert code for properly 21 * registering and deregistering the handlers in except.c. You 22 * should ALWAYS use these macros instead of directly registering 23 * the handlers to avoid accidentally forgetting to deregister 24 * them. If you forget to deregister an exception handler, this 25 * can lead to really strange errors (crashes, hangs) which are 26 * nearly impossible to debug because the thread's stack space 27 * might get completely messed up. 28 * 29 * The general idea of these macros is to define TRY / CATCH 30 * blocks similar to C++. If an exception occurs in the TRY block, 31 * execution is transferred to the CATCH block. (This works in both 32 * C and C++, by the way.) 33 * 34 * The "OnKill" function that was added with V0.9.0 has been 35 * removed again with V0.9.7. Use DosEnterMustComplete instead. 36 * Details follow. 18 * and macros in here are designed to make that more 19 * simple. 20 * 21 * The macros in except.h automatically insert code for 22 * properly registering and deregistering the handlers 23 * in except.c. You should ALWAYS use these macros 24 * instead of directly registering the handlers to avoid 25 * accidentally forgetting to deregister them. If you 26 * forget to deregister an exception handler, this can 27 * lead to really strange errors (crashes, hangs) which 28 * are nearly impossible to debug because the thread's 29 * stack probably got completely messed up. 30 * 31 * The general idea of these macros is to define 32 * TRY / CATCH blocks similar to C++. If an exception 33 * occurs in the TRY block, execution is transferred to 34 * the CATCH block. (This works in both C and C++, by the 35 * way.) 36 * 37 * The "OnKill" function that was added with V0.9.0 has 38 * been removed again with V0.9.7. 37 39 * 38 40 * The general usage is like this: … … 42 44 + TRY_LOUD(excptid) // or: TRY_QUIET(excptid) 43 45 + { 46 + char *p = NULL; 47 + 44 48 + .... // the stuff in here is protected by 45 49 + // the excHandlerLoud or excHandlerQuiet 46 50 + // exception handler 51 + *p = "A"; 47 52 + } 48 53 + CATCH(excptid) … … 58 63 * exception occurs. 59 64 * The CATCH block is _required_ even if you do nothing 60 * in there. 65 * in there, because the CATCH() macro will deregister 66 * the handler. 61 67 * 62 68 * "excptid" can be any C identifier which is not used in … … 78 84 * get called. So if you enclose your main() code in a 79 85 * TRY_* block, your entire application is protected. 86 * If any subfunction fails, execution is transferred to 87 * the closest CATCH() that was installed (as with C++ 88 * try and catch). 80 89 * 81 90 * <B>Asynchronous exceptions</B> … … 83 92 * The exception handlers in this file (which are installed 84 93 * with the TRY/CATCH mechanism) only intercept synchronous 85 * exceptions (see excHandlerLoud for a list). They do not 86 * protect your code against asynchronous exceptions. 94 * exceptions, most importantly, XCPT_ACCESS_VIOLATION (see 95 * excHandlerLoud for a list). They do not protect your code 96 * against asynchronous exceptions. 87 97 * 88 98 * OS/2 defines asynchronous exceptions to be those that … … 100 110 * 101 111 * The problem with OS/2 mutex semaphores is that they are 102 * not automatically released when a thread terminates. 103 * If the thread owning the mutex died without releasing 104 * the mutex, other threads which are blocked on that mutex 105 * will wait forever and become zombie threads. Even worse, 106 * if this happens to a PM thread, this will hang the system. 107 * 108 * Here's the typical scenario with two threads: 109 * 110 * 1) Thread 2 requests a mutex and does lots of processing. 111 * 112 * 2) Thread 1 requests the mutex. Since it's still owned 113 * by thread 2, thread 1 blocks. 114 * 115 * 3) Thread 2 crashes in its processing. Without an 116 * exception handler, OS/2 will terminate the process. 117 * It will first kill thread 2 and then attempt to 118 * kill thread 1. This fails because it is still 119 * blocking on the semaphore that thread 2 never 120 * released. Boom. 121 * 122 * The same scenario happens when a process gets killed. 123 * Since OS/2 will kill secondary threads before thread 1, 124 * the same situation can arise. 125 * 126 * As a result, you must protect any section of code which 127 * requests a semaphore _both_ against crashes _and_ 128 * termination. 112 * sometimes not automatically released when a thread terminates. 113 * If there are several mutexes involved and they are released 114 * in improper order, you can get zombie threads on exit. 115 * Even worse, if this happens to a PM thread, this will hang 116 * the system. 117 * 118 * As a result, you should protect any section of code which 119 * requests a semaphore with the exception handlers. To protect 120 * yourself against thread termination, use must-complete 121 * sections as well (but be careful with those if your code 122 * takes a long time to execute... but then you shouldn't 123 * request a mutex in the first place). 129 124 * 130 125 * So _whenever_ you request a mutex semaphore, enclose … … 141 136 + 142 137 + DosEnterMustComplete(&ulNesting); 143 + TRY_QUIET(excpt1 , OnKillYourFunc)// or TRY_LOUD138 + TRY_QUIET(excpt1) // or TRY_LOUD 144 139 + { 145 + fSemOwned = (WinRequestMutexSem(hmtx, ...) == NO_ERROR);140 + fSemOwned = !WinRequestMutexSem(hmtx, ...); 146 141 + if (fSemOwned) 147 142 + { ... // work on your protected data 148 143 + } 144 + // mutex gets released below 149 145 + } 150 146 + CATCH(excpt1) { } END_CATCH(); // always needed! 151 147 + 152 + if (fSemOwned) { 148 + if (fSemOwned) 149 + { 153 150 + // this gets executed always, even if an exception occured 154 151 + DosReleaseMutexSem(hmtx);
Note:
See TracChangeset
for help on using the changeset viewer.