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