|
|
1.1 ! root 1: .\" Copyright (c) 1980 Regents of the University of California. ! 2: .\" All rights reserved. The Berkeley software License Agreement ! 3: .\" specifies the terms and conditions for redistribution. ! 4: .\" ! 5: .\" @(#)ch10.n 6.2 (Berkeley) 5/14/86 ! 6: .\" ! 7: ." $Header: /na/franz/doc/RCS/ch10.n,v 1.1 83/01/31 07:08:20 jkf Exp $ ! 8: .Lc Exception\ Handling 10 ! 9: .sh 2 Errset\ and\ Error\ Handler\ Functions \n(ch 1 ! 10: .pp ! 11: .Fr ! 12: allows the user to handle in a number of ways the errors ! 13: which arise during computation. ! 14: One way is through the use of the ! 15: .i errset ! 16: function. ! 17: If an error occurs during the evaluation of the ! 18: .i errset 's ! 19: first argument, then ! 20: the locus of control will return to the errset which will ! 21: return nil (except in special cases, such as ! 22: .i err ). ! 23: The other method of error handling is through an error handler ! 24: function. ! 25: When an error occurs, the error handler is called and ! 26: is given as an argument a description of the ! 27: error which just occurred. ! 28: The error handler may take one of the following actions: ! 29: .nr $p 0 ! 30: .np ! 31: it could take some drastic action like a ! 32: .i reset ! 33: or a ! 34: .i throw . ! 35: .np ! 36: it could, assuming that the error is continuable, ! 37: return ! 38: to the function which noticed the error. ! 39: The error handler indicates that it wants to return a value from ! 40: the error by returning a list whose ! 41: .i car ! 42: is the value it wants to return. ! 43: .np ! 44: it could decide not to handle the error and return a non-list to ! 45: indicate this fact. ! 46: .sh 2 "The Anatomy of an error" ! 47: .pp ! 48: Each error is described by a list of these items: ! 49: .nr $p 0 ! 50: .np ! 51: error type - This is a symbol which indicates the ! 52: general classification of the error. ! 53: This classification may determine which function handles this ! 54: error. ! 55: .np ! 56: unique id - This is a fixnum unique to this error. ! 57: .np ! 58: continuable - If this is non-nil then this error is continuable. ! 59: There are some who feel that every error should be continuable ! 60: and the reason that some (in fact most) errors in ! 61: .Fr ! 62: are not continuable is due to the laziness of the programmers. ! 63: .np ! 64: message string - This is a symbol whose print name is a ! 65: message describing the error. ! 66: .np ! 67: data - There may be from zero to three lisp values which help ! 68: describe this particular error. ! 69: For example, the unbound variable error contains one datum value, ! 70: the symbol whose value is unbound. ! 71: The list describing that error might look like: ! 72: .br ! 73: .ce ! 74: (ER%misc 0 t |Unbound Variable:| foobar) ! 75: .sh 2 "Error handling algorithm" ! 76: .pp ! 77: This is the sequence of operations which is done when an ! 78: error occurs: ! 79: .nr $p 0 ! 80: .np ! 81: If the symbol ! 82: .b ER%all ! 83: has a non nil value ! 84: then this value is the name of an error handler function. ! 85: That function is called with a description of the error. ! 86: If that function returns (and of course it may choose not to) ! 87: and the value is a list and this error is continuable, then ! 88: we return the ! 89: .i car ! 90: of the list to the function which called the error. ! 91: Presumably the function will use this value to retry the operation. ! 92: On the other hand, if the error handler returns a non list, then ! 93: it has chosen not to handle this error, so we go on to step (2). ! 94: Something special happens before we call the ! 95: .b ER%all ! 96: error ! 97: handler which does not happen in any of the ! 98: other cases we will describe below. ! 99: To help insure that we don't get infinitely recursive ! 100: errors if ! 101: .b ER%all ! 102: is set to a bad value, ! 103: the value of ! 104: .b ER%all ! 105: is set to nil before the ! 106: handler is called. ! 107: Thus it is the responsibility of the ! 108: .b ER%all ! 109: handler to `reenable' ! 110: itself by storing its name in ! 111: .b ER%all. ! 112: .np ! 113: Next the specific error handler for the type of error ! 114: which just occurred is called (if one exists) to see if ! 115: it wants to handle the error. ! 116: The names of the handlers for the specific types of errors are stored ! 117: as the values of the symbols whose names are the types. ! 118: For example the handler for miscellaneous errors is stored as the ! 119: value of ! 120: .b ER%misc. ! 121: Of course, if ! 122: .b ER%misc ! 123: has a value of nil, then there is no error ! 124: handler for this type of error. ! 125: Appendix B contains list of all error types. ! 126: The process of classifying the errors is not complete and thus most ! 127: errors are lumped into the \fBER%misc\fP category. ! 128: Just as in step (1), ! 129: the error handler function may choose not to handle the error ! 130: by returning a non-list, and then we go to step (3). ! 131: .np ! 132: Next a check is made to see if there is an ! 133: .i errset ! 134: surrounding this error. ! 135: If so the second argument to the ! 136: .i errset ! 137: call ! 138: is examined. ! 139: If the second argument was not given or is non nil ! 140: then the error message associated with this error is printed. ! 141: Finally the stack is popped ! 142: to the context of the ! 143: .i errset ! 144: and then the ! 145: .i errset ! 146: returns nil. ! 147: If there was no ! 148: .i errset ! 149: we go to step (4). ! 150: .np ! 151: If the symbol ! 152: .b ER%tpl ! 153: has a value then it is the ! 154: name of an error handler which is called in a manner similar ! 155: to that discussed above. ! 156: If it chooses not to handle the error, we go to step (5). ! 157: .np ! 158: At this point it has been determined that the user doesn't ! 159: want to handle this error. ! 160: Thus the error message is printed out and ! 161: a ! 162: .i reset ! 163: is done to send the flow of control to the top-level. ! 164: .pp ! 165: To summarize the error handling system: ! 166: When an error occurs, you have two chances to handle it before ! 167: the search for an ! 168: .i errset ! 169: is done. ! 170: Then, if there is no ! 171: .i errset , ! 172: you have one more chance to handle the error before control ! 173: jumps to the top level. ! 174: Every error handler works in the same way: ! 175: It is given a description of the error (as described in the ! 176: previous section). ! 177: It may or may not return. ! 178: If it returns, then it returns ! 179: either a list or a non-list. ! 180: If it returns a list and the error is continuable, then ! 181: the ! 182: .i car ! 183: of the list is returned to the function which noticed the error. ! 184: Otherwise the error handler has decided not to handle the error ! 185: and we go on to something else. ! 186: .sh 2 "Default aids" ! 187: .pp ! 188: There are two standard error handlers which will probably ! 189: handle the needs of most users. ! 190: One of these is the lisp coded function ! 191: .i break-err-handler ! 192: which is the default value of ! 193: .b ER%tpl. ! 194: Thus when all other handlers have ignored an error, ! 195: .i break-err-handler ! 196: will take over. ! 197: It will print out the error message and ! 198: go into a read-eval-print loop. ! 199: The other standard error handler is ! 200: .i debug-err-handler . ! 201: This handler is designed to be connected to ! 202: .b ER%all and ! 203: is useful if your program uses ! 204: .i errset ! 205: and you want to ! 206: look at the error before ! 207: it is thrown up to the ! 208: .i errset . ! 209: .sh +0 Autoloading ! 210: .pp ! 211: When ! 212: .i eval , ! 213: .i apply ! 214: or ! 215: .i funcall ! 216: are told to call an undefined function, an \fBER%undef\fP ! 217: error is signaled. ! 218: The default handler for this error is ! 219: .i undef-func-handler . ! 220: This function checks the property list of the undefined function for ! 221: the indicator autoload. ! 222: If present, the value of that indicator should be the name of the file ! 223: which contains the definition of the undefined function. ! 224: .i Undef-func-handler ! 225: will load the file and check if it has defined the function which caused ! 226: the error. ! 227: If it has, the error handler will return and the computation will continue ! 228: as if the error did not occur. ! 229: This provides a way for the user to tell the lisp system about the location ! 230: of commonly used functions. ! 231: The trace package sets up an autoload property to point to /usr/lib/lisp/trace. ! 232: .sh +0 Interrupt\ processing ! 233: .pp ! 234: The UNIX operating system provides one user interrupt character which ! 235: defaults to ^C.\*[\(dg\*] ! 236: .(f ! 237: \*[\(dg\*]Actually there are two but the lisp system does not allow you ! 238: to catch the QUIT interrupt. ! 239: .)f ! 240: The user may select a lisp function to run when an interrupt occurs. ! 241: Since this interrupt could occur at any time, and in particular could ! 242: occur at a time when the internal stack pointers were in an inconsistent ! 243: state, the processing of the interrupt may be delayed until a safe ! 244: time. ! 245: When the first ^C is typed, the lisp system sets a flag that an interrupt ! 246: has been requested. ! 247: This flag is checked at safe places within the interpreter ! 248: and in the ! 249: .i qlinker ! 250: function. ! 251: If the lisp system doesn't respond to the first ^C, another ^C should ! 252: be typed. ! 253: This will cause all of the transfer tables to be cleared forcing ! 254: all calls from compiled code to go through the ! 255: .i qlinker ! 256: function where the interrupt flag will be checked. ! 257: If the lisp system still doesn't respond, a third ^C will cause ! 258: an immediate interrupt. ! 259: This interrupt will not necessarily be in a safe place so the ! 260: user should ! 261: .i reset ! 262: the lisp system as soon as possible.
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.