Commit | Line | Data |
---|---|---|
3603109f NC |
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 | .\" | |
f37da2f3 | 5 | .\" @(#)ch10.n 6.1 (Berkeley) %G% |
3603109f | 6 | .\" |
f37da2f3 NC |
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 10 | |
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. |