author | Claus Gittinger <cg@exept.de> |
Sat, 15 Nov 1997 15:06:27 +0100 | |
changeset 3111 | a23fa6d08ce7 |
parent 3110 | 9a1e3a736e14 |
child 3179 | f22e94c6ae83 |
permissions | -rw-r--r-- |
1 | 1 |
" |
2 |
COPYRIGHT (c) 1993 by Claus Gittinger |
|
171 | 3 |
All Rights Reserved |
1 | 4 |
|
5 |
This software is furnished under a license and may be used |
|
6 |
only in accordance with the terms of that license and with the |
|
7 |
inclusion of the above copyright notice. This software may not |
|
8 |
be provided or otherwise made available to, or used by, any |
|
9 |
other person. No title to or ownership of the software is |
|
10 |
hereby transferred. |
|
11 |
" |
|
12 |
||
13 |
Object subclass:#Exception |
|
1118
1037616d9add
ignore unhandled querySignals
Claus Gittinger <cg@exept.de>
parents:
1038
diff
changeset
|
14 |
instanceVariableNames:'signal parameter errorString suspendedContext handlerContext |
759
908363ce8a32
interest is written with one 'r' (shame on me)
Claus Gittinger <cg@exept.de>
parents:
662
diff
changeset
|
15 |
rejected originator resumeBlock rejectBlock' |
1118
1037616d9add
ignore unhandled querySignals
Claus Gittinger <cg@exept.de>
parents:
1038
diff
changeset
|
16 |
classVariableNames:'EmergencyHandler RecursiveExceptionSignal' |
1037616d9add
ignore unhandled querySignals
Claus Gittinger <cg@exept.de>
parents:
1038
diff
changeset
|
17 |
poolDictionaries:'' |
1037616d9add
ignore unhandled querySignals
Claus Gittinger <cg@exept.de>
parents:
1038
diff
changeset
|
18 |
category:'Kernel-Exceptions' |
1 | 19 |
! |
20 |
||
1953
c8a3af54acb3
unhandled querySignals should return nil
Claus Gittinger <cg@exept.de>
parents:
1710
diff
changeset
|
21 |
!Exception class methodsFor:'documentation'! |
12 | 22 |
|
88 | 23 |
copyright |
24 |
" |
|
25 |
COPYRIGHT (c) 1993 by Claus Gittinger |
|
171 | 26 |
All Rights Reserved |
88 | 27 |
|
28 |
This software is furnished under a license and may be used |
|
29 |
only in accordance with the terms of that license and with the |
|
30 |
inclusion of the above copyright notice. This software may not |
|
31 |
be provided or otherwise made available to, or used by, any |
|
32 |
other person. No title to or ownership of the software is |
|
33 |
hereby transferred. |
|
34 |
" |
|
35 |
! |
|
36 |
||
12 | 37 |
documentation |
38 |
" |
|
68 | 39 |
Instances of Exception are passed to a Signal handling block as argument. |
40 |
The handler block may perform various actions by sending corresponding messages |
|
142 | 41 |
to the exception object. The following actions are possible: |
1 | 42 |
|
2208 | 43 |
reject - dont handle this signal; |
44 |
another handler will be searched for, |
|
45 |
upper in the calling hierarchy |
|
1 | 46 |
|
2208 | 47 |
proceed - return from the Signal>>raise, with nil as value |
142 | 48 |
|
2208 | 49 |
proceedWith:val - same, but return val from Signal>>raise |
1 | 50 |
|
2208 | 51 |
return - return from the Signal>>handle:do:, with nil as value |
142 | 52 |
|
2208 | 53 |
returnWith:val - same, but return val from Signal>>handle:do: |
54 |
(this is also the handlers default, |
|
55 |
if it falls through; taking the handlerBlocks value |
|
56 |
as return value) |
|
1 | 57 |
|
2208 | 58 |
restart - restart the Signal>>handle:do:, after repairing |
1 | 59 |
|
142 | 60 |
Via the Exception object, the handler can also query the state of execution: |
68 | 61 |
where the Signal was raised, where the handler is, the signal which caused |
142 | 62 |
the error and the errorString passed when the signal was raised. Also, an optional |
63 |
parameter can be passed - the use is signal specific.: |
|
44 | 64 |
|
1274 | 65 |
[instance variables:] |
2208 | 66 |
signal <Signal> the signal which caused the exception |
142 | 67 |
|
2208 | 68 |
parameter <Object> a parameter (if any) which was passed when raising |
69 |
the signal (only if raised with #raiseWith:aParameter) |
|
142 | 70 |
|
2208 | 71 |
errorString <String> an errorString |
72 |
(usually the signals own errorString, but sometimes |
|
73 |
changed explicitely in #raiseWith:errorString:) |
|
44 | 74 |
|
2208 | 75 |
suspendedContext <Context> the context in which the raise occured |
142 | 76 |
|
2208 | 77 |
handlerContext <Context> the context of the handler (if any) |
142 | 78 |
|
2208 | 79 |
resumeBlock <Block> private to the exception; needed to perform resume action |
44 | 80 |
|
2208 | 81 |
rejectBlock <Block> private to the exception; needed to perform reject action |
44 | 82 |
|
142 | 83 |
In case of an unhandled signal raise, Exceptions EmergenyHandler will be evaluated. |
68 | 84 |
The default emergeny handler will enter the debugger. |
142 | 85 |
|
68 | 86 |
For applications, which do not want Debuggers to come up, other handlers are |
87 |
possible. |
|
362 | 88 |
For example, to get the typical C++ behavior, use: |
2208 | 89 |
Exception emergencyHandler:[:ex | Smalltalk exitWithCoreDump] |
68 | 90 |
|
1274 | 91 |
|
92 |
[Class variables:] |
|
2208 | 93 |
EmergencyHandler <Block> this block is evaluated, if no handler was defined |
94 |
for a signal (i.e. this one is responsible for the |
|
95 |
unhandled exception debugger). |
|
96 |
Having this being a block allows to globally catch |
|
97 |
these errors - even when no enclosing handler-scope |
|
98 |
around the erronous code exists. |
|
99 |
(as the catch/through does). |
|
171 | 100 |
|
2208 | 101 |
RecursiveExceptionSignal |
102 |
<Signal> raised when within a handler for some signal, |
|
103 |
the same signal is raised again. |
|
1274 | 104 |
|
105 |
||
106 |
[see also:] |
|
2208 | 107 |
Signal SignalSet QuerySignal |
108 |
Context Block |
|
109 |
Object DebugView |
|
110 |
(``Exception handling and signals'': programming/exceptions.html) |
|
1292 | 111 |
|
112 |
[author:] |
|
2208 | 113 |
Claus Gittinger |
12 | 114 |
" |
2174 | 115 |
! |
116 |
||
117 |
examples |
|
118 |
" |
|
119 |
Examples on Exception-raising & handling are found in the doc/coding |
|
120 |
section (CodingExamples). |
|
121 |
||
122 |
The emergencyHandler stuff is very useful, to prevent endUser applications |
|
123 |
from entering the debugger. |
|
124 |
Some commonly used (useful) emergency handlers are provided in the |
|
125 |
'useful handlers' section; try them to learn more |
|
126 |
(especially, the mailingHandler is fun). |
|
127 |
||
2219 | 128 |
Of course, these are only examples - you may define your own handler |
129 |
block and pass it to the #emergencyHandler: method. |
|
130 |
||
131 |
BTW: the Launchers 'source & debugger' settings menu allows you |
|
132 |
to install either a default or the notifying handler. |
|
133 |
||
134 |
||
135 |
A handler which shows a box, then aborts - (no more debuggers): |
|
136 |
[exBegin] |
|
137 |
Exception emergencyHandler:(Exception abortingEmergencyHandler) |
|
138 |
[exEnd] |
|
139 |
||
140 |
||
141 |
A handler which aborts - (no box, no debugger): |
|
142 |
[exBegin] |
|
143 |
Exception emergencyHandler:[:ex | AbortSignal raise] |
|
144 |
[exEnd] |
|
2174 | 145 |
|
146 |
||
147 |
try some exception (for demonstration, in some other process): |
|
2219 | 148 |
[exBegin] |
149 |
[ |
|
150 |
#(1 2 3) at:4 |
|
151 |
] fork. |
|
152 |
[exEnd] |
|
2174 | 153 |
|
2219 | 154 |
cleanup (switch back to the regular handler, which enters the debugger): |
155 |
[exBegin] |
|
156 |
Exception emergencyHandler:nil |
|
157 |
[exEnd] |
|
158 |
||
159 |
||
160 |
A handler which shows a warnBox and asks for debugging: |
|
161 |
[exBegin] |
|
162 |
Exception emergencyHandler:(Exception notifyingEmergencyHandler) |
|
163 |
[exEnd] |
|
164 |
||
2174 | 165 |
|
166 |
||
167 |
A handler which dumps information to a file (watch the file 'errorTrace.stx'): |
|
2219 | 168 |
[exBegin] |
169 |
Exception emergencyHandler:(Exception dumpingEmergencyHandler) |
|
170 |
[exEnd] |
|
171 |
||
172 |
||
2174 | 173 |
|
174 |
A handler which sends you mail: |
|
2219 | 175 |
[exBegin] |
176 |
Exception emergencyHandler:(Exception mailingEmergencyHandler) |
|
177 |
[exEnd] |
|
2174 | 178 |
" |
12 | 179 |
! ! |
3 | 180 |
|
1953
c8a3af54acb3
unhandled querySignals should return nil
Claus Gittinger <cg@exept.de>
parents:
1710
diff
changeset
|
181 |
!Exception class methodsFor:'initialization'! |
171 | 182 |
|
183 |
initialize |
|
184 |
"setup the signal used to handle unhandled signals" |
|
185 |
||
186 |
RecursiveExceptionSignal isNil ifTrue:[ |
|
302 | 187 |
RecursiveExceptionSignal := ErrorSignal newSignalMayProceed:false. |
171 | 188 |
RecursiveExceptionSignal nameClass:self message:#recursiveExceptionSignal. |
189 |
RecursiveExceptionSignal notifierString:'recursive signal raise in handler' |
|
190 |
] |
|
191 |
! ! |
|
192 |
||
1953
c8a3af54acb3
unhandled querySignals should return nil
Claus Gittinger <cg@exept.de>
parents:
1710
diff
changeset
|
193 |
!Exception class methodsFor:'instance creation'! |
621 | 194 |
|
195 |
signal:aSignal parameter:aParameter errorString:aString suspendedContext:sContext |
|
196 |
"create a new instance and set the fields in preparation for a raise. |
|
197 |
- only to be sent from the signal when raising" |
|
198 |
||
3091 | 199 |
"{ Pragma: +inlineNew }" |
200 |
||
3017 | 201 |
^ (self basicNew) |
621 | 202 |
signal:aSignal |
203 |
parameter:aParameter |
|
204 |
errorString:aString |
|
205 |
suspendedContext:sContext |
|
206 |
originator:(sContext receiver). |
|
207 |
! |
|
208 |
||
209 |
signal:aSignal parameter:aParameter errorString:aString suspendedContext:sContext originator:origin |
|
210 |
"create a new instance and set the fields in preparation for a raise. |
|
211 |
- only to be sent from the signal when raising" |
|
212 |
||
3091 | 213 |
"{ Pragma: +inlineNew }" |
214 |
||
3017 | 215 |
^ (self basicNew) |
621 | 216 |
signal:aSignal |
217 |
parameter:aParameter |
|
218 |
errorString:aString |
|
219 |
suspendedContext:sContext |
|
220 |
originator:origin. |
|
221 |
! ! |
|
222 |
||
1953
c8a3af54acb3
unhandled querySignals should return nil
Claus Gittinger <cg@exept.de>
parents:
1710
diff
changeset
|
223 |
!Exception class methodsFor:'Signal constants'! |
171 | 224 |
|
225 |
recursiveExceptionSignal |
|
226 |
"return the signal used to handle recursive signals in the handlers" |
|
227 |
||
228 |
^ RecursiveExceptionSignal |
|
229 |
! ! |
|
230 |
||
1953
c8a3af54acb3
unhandled querySignals should return nil
Claus Gittinger <cg@exept.de>
parents:
1710
diff
changeset
|
231 |
!Exception class methodsFor:'defaults'! |
12 | 232 |
|
233 |
emergencyHandler |
|
2174 | 234 |
"return the handler used for unhandled exceptions. |
235 |
||
236 |
If no EmergencyHandler has been set, a handler which enters the |
|
237 |
debugger is returned. |
|
238 |
The debugger is opened by asking the signal for a debug action, |
|
239 |
this allows to provide other debuggers in specialized (subclass-instances) |
|
240 |
of Signal (if that is ever needed)" |
|
12 | 241 |
|
77 | 242 |
" |
243 |
set it up, when called the first time |
|
244 |
" |
|
245 |
EmergencyHandler isNil ifTrue:[ |
|
2208 | 246 |
EmergencyHandler := [:ex | |
247 |
" |
|
248 |
sending it to the signal allows per-signal specific |
|
249 |
debuggers to be implemented in the future |
|
250 |
(for example, segv in primitive code could show things |
|
251 |
on the C-level ..) |
|
252 |
" |
|
253 |
(ex signal) enterDebuggerWith:ex message:(ex errorString). |
|
254 |
] |
|
77 | 255 |
]. |
256 |
||
12 | 257 |
^ EmergencyHandler |
2174 | 258 |
|
259 |
"Modified: 15.1.1997 / 20:50:37 / cg" |
|
12 | 260 |
! |
261 |
||
130 | 262 |
emergencyHandler:aOneArgBlock |
2174 | 263 |
"set the handler used for unhandled exceptions. |
264 |
The default (a nil-handler) leads to a debugger to be shown." |
|
12 | 265 |
|
130 | 266 |
EmergencyHandler := aOneArgBlock |
362 | 267 |
|
268 |
"ST-80 behavior of first showing a notifier: |
|
269 |
(I prefer to get right into the debugger, though) |
|
270 |
||
271 |
Exception |
|
2208 | 272 |
emergencyHandler: |
273 |
[:ex | self errorNotify:ex errorString ] |
|
2081 | 274 |
" |
275 |
||
276 |
"ST-X behavior of going right into the debugger: |
|
277 |
||
278 |
Exception |
|
2208 | 279 |
emergencyHandler:nil |
362 | 280 |
" |
281 |
||
282 |
"automatically aborting current operation, on error: |
|
283 |
(may be useful for end-user apps; make certain, |
|
284 |
you have abortSignal handlers at appropriate places) |
|
285 |
||
286 |
Exception |
|
2208 | 287 |
emergencyHandler: |
288 |
[:ex | Object abortSignal raise. ex return. ] |
|
362 | 289 |
" |
290 |
||
291 |
"finally, traditional language system behavior; dump core ;-) |
|
292 |
||
293 |
Exception |
|
2208 | 294 |
emergencyHandler: |
295 |
[:ex | Smalltalk exitWithCoreDump. ] |
|
362 | 296 |
" |
2081 | 297 |
|
2174 | 298 |
"Modified: 15.1.1997 / 20:49:06 / cg" |
299 |
! ! |
|
300 |
||
301 |
!Exception class methodsFor:'useful handlers'! |
|
302 |
||
303 |
abortingEmergencyHandler |
|
304 |
"return a block (usable as an emergency handler), |
|
305 |
which aborts after showing a warnBox. |
|
306 |
This is useful for endUser applications" |
|
307 |
||
308 |
^ [:ex | self warn:'Error: ' , ex errorString. |
|
2208 | 309 |
AbortSignal raise |
2174 | 310 |
] |
311 |
||
312 |
"test with (try a few halts or CTRL-C's): |
|
313 |
Exception emergencyHandler:(Exception abortingEmergencyHandler) |
|
314 |
" |
|
315 |
||
316 |
"back with: |
|
317 |
Exception emergencyHandler:(Exception notifyingEmergencyHandler) |
|
318 |
Exception emergencyHandler:nil |
|
319 |
" |
|
320 |
||
321 |
"Created: 15.1.1997 / 20:13:06 / cg" |
|
322 |
"Modified: 15.1.1997 / 20:15:02 / cg" |
|
323 |
! |
|
324 |
||
325 |
dumpingEmergencyHandler |
|
326 |
"return a block (usable as an emergency handler), |
|
327 |
which dumps the stackBacktrace to a trace file and |
|
328 |
aborts after showing a warnBox. |
|
329 |
This is useful, for endUser application, which are still being |
|
330 |
debugged (i.e. the programmers may have a look at the traceFile |
|
331 |
from time to time). |
|
332 |
||
333 |
Notice: |
|
2257 | 334 |
The code below is just an example; you may want to change the |
335 |
name of the error-file in your application |
|
336 |
(but please: copy the code; do not modify here)" |
|
2174 | 337 |
|
338 |
^ [:ex | |
|
2257 | 339 |
|str printedException| |
2174 | 340 |
|
2257 | 341 |
ex signal == Signal noHandlerSignal ifTrue:[ |
342 |
printedException := ex parameter. |
|
343 |
] ifFalse:[ |
|
344 |
printedException := ex |
|
345 |
]. |
|
346 |
||
347 |
"/ user interruption is handled specially: |
|
348 |
"/ allow user to choose between proceeding or aborting |
|
349 |
"/ but never dump that information to the file. |
|
2174 | 350 |
|
2257 | 351 |
printedException signal == Object userInterruptSignal ifTrue:[ |
352 |
(self confirm:'abort current action ?') ifTrue:[ |
|
353 |
AbortSignal raise |
|
354 |
]. |
|
355 |
ex proceed |
|
356 |
]. |
|
2174 | 357 |
|
2257 | 358 |
"/ |
359 |
"/ dump it to 'errorTrace.stx' |
|
360 |
"/ |
|
361 |
str := 'errorTrace.stx' asFilename appendingWriteStream. |
|
2174 | 362 |
|
2257 | 363 |
str nextPutLine:('******************************* ' |
364 |
, AbsoluteTime now printString |
|
365 |
, ' *******************************'). |
|
366 |
str cr. |
|
2174 | 367 |
|
2257 | 368 |
str nextPutLine:('** Error: ' , printedException errorString). |
369 |
str nextPutLine:('** Signal: ' , printedException signal printString). |
|
370 |
str nextPutLine:('** Parameter: ' , printedException parameter printString). |
|
371 |
str nextPutLine:('** Process: ' , Processor activeProcess printString). |
|
372 |
str nextPutLine:('** Backtrace:'). |
|
373 |
str cr. |
|
2174 | 374 |
|
2257 | 375 |
printedException suspendedContext fullPrintAllOn:str. |
376 |
str cr. |
|
377 |
str cr. |
|
378 |
str close. |
|
2174 | 379 |
|
2257 | 380 |
"/ send a line to stdErr |
381 |
||
382 |
('[warning]: ignored error: ' , printedException errorString) errorPrintCR. |
|
383 |
('[warning]: error information appended to ''errorTrace.stx''') errorPrintCR. |
|
384 |
||
385 |
AbortSignal raise |
|
2174 | 386 |
] |
387 |
||
388 |
"test with (try a few halts or CTRL-C's): |
|
389 |
Exception emergencyHandler:(Exception dumpingEmergencyHandler) |
|
390 |
" |
|
391 |
||
392 |
"back with: |
|
393 |
Exception emergencyHandler:(Exception notifyingEmergencyHandler) |
|
394 |
Exception emergencyHandler:nil |
|
395 |
" |
|
396 |
||
397 |
"Created: 15.1.1997 / 20:14:52 / cg" |
|
2257 | 398 |
"Modified: 24.1.1997 / 20:36:21 / cg" |
2174 | 399 |
! |
400 |
||
401 |
mailingEmergencyHandler |
|
402 |
"return a block (usable as an emergency handler), |
|
403 |
which shows a warnBox and optionally mails a stackBacktrace to a maintainer. |
|
404 |
This is useful, for endUser application, which are still being |
|
405 |
debugged (i.e. the programmers may have a look at the errors). |
|
406 |
||
407 |
Notice: the stuff here is a demonstration only; it should be modified |
|
2208 | 408 |
for your particular environment ... |
409 |
... but please: copy the code and modify there; |
|
410 |
leave the stuff below as it is." |
|
2174 | 411 |
|
412 |
^ [:ex | |
|
2208 | 413 |
|str printedException doMail emergencyMailReceiver pipe| |
2174 | 414 |
|
2208 | 415 |
ex signal == Signal noHandlerSignal ifTrue:[ |
416 |
printedException := ex parameter. |
|
417 |
] ifFalse:[ |
|
418 |
printedException := ex |
|
419 |
]. |
|
2174 | 420 |
|
2208 | 421 |
"/ user interruption is handled specially: |
422 |
"/ allow user to choose between proceeding or aborting |
|
423 |
"/ but never dump that information to the file. |
|
2174 | 424 |
|
2208 | 425 |
printedException signal == Object userInterruptSignal ifTrue:[ |
426 |
(self confirm:'abort current action ?') ifTrue:[ |
|
427 |
AbortSignal raise |
|
428 |
]. |
|
429 |
ex proceed |
|
430 |
]. |
|
2174 | 431 |
|
2208 | 432 |
"/ somehow get the name of the guy to receive the mail |
433 |
"/ you have to implement that yourself. |
|
2174 | 434 |
|
2208 | 435 |
"/ emergencyMailReceiver := OneOfYourClass getEmergencyMailReceiver. |
436 |
emergencyMailReceiver := OperatingSystem getLoginName. |
|
2174 | 437 |
|
2208 | 438 |
emergencyMailReceiver isNil ifTrue:[ |
439 |
self warn:(printedException errorString |
|
440 |
, '\\No mailing to service people possible.') withCRs. |
|
441 |
doMail := false. |
|
442 |
] ifFalse:[ |
|
443 |
doMail := self confirm:(printedException errorString |
|
444 |
, '\\Mail error information to the service people (' |
|
445 |
, emergencyMailReceiver , ') ?') withCRs |
|
446 |
]. |
|
447 |
doMail ifTrue:[ |
|
448 |
str := '' writeStream. |
|
2174 | 449 |
|
2208 | 450 |
str nextPutLine:('Error notification from ' |
451 |
, OperatingSystem getLoginName |
|
452 |
, '@' |
|
453 |
, OperatingSystem getHostName). |
|
454 |
str cr. |
|
2174 | 455 |
|
2208 | 456 |
str nextPutLine:('Time: ' , AbsoluteTime now printString). |
457 |
str nextPutLine:('Error: ', printedException errorString). |
|
458 |
str nextPutLine:('Signal: ', printedException signal printString). |
|
459 |
str nextPutLine:('Parameter: ', printedException parameter printString). |
|
460 |
str nextPutLine:('Process: ', Processor activeProcess printString). |
|
461 |
str nextPutLine:'Backtrace:'. |
|
462 |
str cr. |
|
2174 | 463 |
|
2208 | 464 |
printedException suspendedContext fullPrintAllOn:str. |
465 |
str cr;cr. |
|
2174 | 466 |
|
2208 | 467 |
str close. |
2174 | 468 |
|
2208 | 469 |
pipe := PipeStream |
470 |
writingTo:'mail ', emergencyMailReceiver. |
|
471 |
pipe notNil ifTrue:[ |
|
472 |
pipe nextPutLine:'Subject: automatic error report'. |
|
473 |
pipe nextPutAll:str contents. |
|
474 |
pipe cr. |
|
475 |
pipe close. |
|
476 |
] |
|
477 |
]. |
|
2174 | 478 |
|
2208 | 479 |
AbortSignal raise |
2174 | 480 |
] |
481 |
||
482 |
"test with (try a few halts or CTRL-C's): |
|
483 |
Exception emergencyHandler:(Exception mailingEmergencyHandler) |
|
484 |
" |
|
485 |
||
486 |
"back with: |
|
487 |
Exception emergencyHandler:(Exception notifyingEmergencyHandler) |
|
488 |
Exception emergencyHandler:nil |
|
489 |
" |
|
490 |
||
491 |
"Created: 15.1.1997 / 20:14:52 / cg" |
|
492 |
"Modified: 15.1.1997 / 21:10:28 / cg" |
|
493 |
! |
|
494 |
||
495 |
notifyingEmergencyHandler |
|
496 |
"return a block (usable as an emergency handler for exceptions), |
|
497 |
which does errorNotification before going into the debugger." |
|
498 |
||
499 |
^ [:ex | nil errorNotify:ex errorString from:ex suspendedContext ] |
|
500 |
||
501 |
"test with (try a few halts or CTRL-C's): |
|
502 |
Exception emergencyHandler:(Exception notifyingEmergencyHandler) |
|
503 |
" |
|
504 |
||
505 |
"back with: |
|
506 |
Exception emergencyHandler:nil |
|
507 |
" |
|
508 |
||
509 |
"Modified: 15.1.1997 / 20:15:12 / cg" |
|
362 | 510 |
! ! |
511 |
||
1 | 512 |
!Exception methodsFor:'accessing'! |
513 |
||
44 | 514 |
errorString |
515 |
"return the errorString passsed with the signal raise |
|
516 |
(or nil, if there was none)" |
|
517 |
||
518 |
^ errorString |
|
519 |
! |
|
520 |
||
621 | 521 |
handlerContext |
522 |
"return the context of the handler" |
|
523 |
||
524 |
^ handlerContext |
|
525 |
! |
|
526 |
||
362 | 527 |
originator |
528 |
"return the originator passsed with the signal raise |
|
529 |
(or nil, if there was none)" |
|
530 |
||
531 |
^ originator |
|
532 |
! |
|
533 |
||
621 | 534 |
parameter |
535 |
"return the parameter passsed with the signal raise |
|
536 |
(or nil, if there was none)" |
|
44 | 537 |
|
621 | 538 |
^ parameter |
68 | 539 |
! |
540 |
||
541 |
rejected |
|
362 | 542 |
"return true, if any other of the exceptions handlers has rejected |
759
908363ce8a32
interest is written with one 'r' (shame on me)
Claus Gittinger <cg@exept.de>
parents:
662
diff
changeset
|
543 |
Uncertain, if this is really interesting to anybody. |
362 | 544 |
This is only valid during handler execution. |
545 |
(i.e. an outer handler can find out, if any other handler has already |
|
546 |
rejected). |
|
547 |
" |
|
68 | 548 |
|
549 |
^ rejected |
|
362 | 550 |
! |
551 |
||
621 | 552 |
signal |
553 |
"return the signal, that caused the exception" |
|
554 |
||
555 |
^ signal |
|
556 |
! |
|
557 |
||
558 |
suspendedContext |
|
559 |
"return the context in which the raise occured" |
|
560 |
||
561 |
^ suspendedContext |
|
562 |
! |
|
563 |
||
362 | 564 |
willProceed |
565 |
"return true, if the exception is proceedable" |
|
566 |
||
567 |
^ resumeBlock notNil |
|
1 | 568 |
! ! |
569 |
||
621 | 570 |
!Exception methodsFor:'handler actions'! |
571 |
||
572 |
proceed |
|
573 |
"Continue after the raise - the raise returns nil" |
|
574 |
||
2509
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
575 |
|b| |
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
576 |
|
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
577 |
resumeBlock notNil ifTrue:[ |
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
578 |
b := resumeBlock. |
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
579 |
resumeBlock := rejectBlock := handlerContext := suspendedContext := nil. |
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
580 |
b value:nil |
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
581 |
] |
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
582 |
|
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
583 |
"Modified: 27.3.1997 / 16:44:39 / cg" |
621 | 584 |
! |
585 |
||
586 |
proceedWith:value |
|
587 |
"Continue after the raise - the raise returns value" |
|
588 |
||
2509
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
589 |
|b| |
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
590 |
|
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
591 |
resumeBlock notNil ifTrue:[ |
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
592 |
b := resumeBlock. |
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
593 |
resumeBlock := rejectBlock := handlerContext := suspendedContext := nil. |
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
594 |
b value:value |
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
595 |
] |
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
596 |
|
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
597 |
"Modified: 27.3.1997 / 16:45:57 / cg" |
621 | 598 |
! |
1 | 599 |
|
621 | 600 |
reject |
601 |
"handler decided not to handle this signal - |
|
602 |
system will look for another handler" |
|
603 |
||
604 |
rejected := true. |
|
605 |
rejectBlock value |
|
606 |
! |
|
607 |
||
608 |
restart |
|
609 |
"restart the handle:do: - usually after some repair work is done |
|
610 |
in handler" |
|
611 |
||
612 |
handlerContext unwindAndRestart |
|
613 |
! |
|
1 | 614 |
|
3100 | 615 |
restartDo:aBlock |
616 |
"restart the handle:do: but execute the argument, aBlock instead of the |
|
617 |
original do-block - usually after some repair work is done in handler" |
|
618 |
||
619 |
handlerContext argAt:2 put:aBlock. |
|
620 |
handlerContext unwindAndRestart |
|
621 |
||
622 |
" |
|
623 |
|sig rslt| |
|
624 |
||
625 |
sig := Signal new. |
|
626 |
||
627 |
sig handle:[:ex | |
|
628 |
ex restartDo:[ rslt := 999 ] |
|
629 |
] do:[ |
|
630 |
rslt := 0. |
|
631 |
sig raise |
|
632 |
]. |
|
633 |
||
634 |
Transcript showCR:rslt |
|
635 |
" |
|
636 |
||
637 |
"Modified: / 8.11.1997 / 18:52:28 / cg" |
|
638 |
! |
|
639 |
||
621 | 640 |
resume |
641 |
"Continue after the raise - the raise returns nil" |
|
642 |
||
2509
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
643 |
|b| |
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
644 |
|
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
645 |
resumeBlock notNil ifTrue:[ |
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
646 |
b := resumeBlock. |
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
647 |
resumeBlock := rejectBlock := handlerContext := suspendedContext := nil. |
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
648 |
b value:nil |
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
649 |
] |
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
650 |
|
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
651 |
"Modified: 27.3.1997 / 16:45:18 / cg" |
621 | 652 |
! |
653 |
||
654 |
resumeWith:value |
|
655 |
"Continue after the raise - the raise returns value" |
|
656 |
||
2509
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
657 |
|b| |
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
658 |
|
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
659 |
resumeBlock notNil ifTrue:[ |
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
660 |
b := resumeBlock. |
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
661 |
resumeBlock := rejectBlock := handlerContext := suspendedContext := nil. |
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
662 |
b value:value |
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
663 |
] |
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
664 |
|
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
665 |
"Modified: 27.3.1997 / 16:45:41 / cg" |
621 | 666 |
! |
667 |
||
668 |
return |
|
669 |
"Continue after the handle:do: - the handle:do: returns nil" |
|
670 |
||
2509
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
671 |
|con| |
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
672 |
|
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
673 |
con := handlerContext. |
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
674 |
resumeBlock := rejectBlock := handlerContext := suspendedContext := nil. |
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
675 |
con unwind |
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
676 |
|
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
677 |
"Modified: 27.3.1997 / 16:46:39 / cg" |
621 | 678 |
! |
679 |
||
680 |
returnDoing:aBlock |
|
681 |
"Continue after the handle:do: - the handle:do: returns aBlock value" |
|
682 |
||
683 |
handlerContext unwindThenDo:aBlock |
|
684 |
! |
|
685 |
||
686 |
returnWith:value |
|
687 |
"Continue after the handle:do: - the handle:do: returns value" |
|
688 |
||
2509
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
689 |
|con| |
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
690 |
|
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
691 |
con := handlerContext. |
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
692 |
resumeBlock := rejectBlock := handlerContext := suspendedContext := nil. |
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
693 |
con unwind:value |
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
694 |
|
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
695 |
"Modified: 27.3.1997 / 16:46:51 / cg" |
171 | 696 |
! ! |
697 |
||
217 | 698 |
!Exception methodsFor:'raising'! |
1 | 699 |
|
621 | 700 |
doCallHandler:aHandler |
701 |
"call the handler proper - needed an extra method |
|
702 |
to have a separate returnContext for the rejectBlock. |
|
703 |
(which is historical, and actually no longer needed)" |
|
704 |
||
705 |
|val| |
|
362 | 706 |
|
621 | 707 |
rejectBlock := [^ self]. "this will return on reject" |
708 |
val := aHandler value:self. |
|
709 |
" |
|
710 |
handler fall through - is just like a returnWith:blocks-value |
|
711 |
" |
|
2291
af7652b82404
avoid touching contexts (making them nonLifo) when searching for unwind-contexts,
Claus Gittinger <cg@exept.de>
parents:
2282
diff
changeset
|
712 |
rejectBlock := nil. |
621 | 713 |
self returnWith:val |
1 | 714 |
! |
715 |
||
1378
056b3a0928f2
oops - the last one was bogus
Claus Gittinger <cg@exept.de>
parents:
1376
diff
changeset
|
716 |
doRaise |
171 | 717 |
"search through the context-calling chain for a 'handle:do:'-context |
1609
21f69f2adef7
when skipping active handlers, must not only look for
Claus Gittinger <cg@exept.de>
parents:
1482
diff
changeset
|
718 |
to the raising signal, a parent of it, or a SignalSet which includes |
171 | 719 |
the raising signal. |
720 |
If found, take the contexts 2nd argument (the handler) and evaluate |
|
721 |
it with the receiver exception as argument. |
|
217 | 722 |
If no handler is found, try per signal handler, or |
723 |
per process handler (if its the noHandlerSignal). |
|
724 |
Finally fall back to Exceptions emergencyHandler, which is always |
|
1482
f4b65def90e1
oops - correctly look for handlers when exceptions
Claus Gittinger <cg@exept.de>
parents:
1378
diff
changeset
|
725 |
available and enters the debugger. |
f4b65def90e1
oops - correctly look for handlers when exceptions
Claus Gittinger <cg@exept.de>
parents:
1378
diff
changeset
|
726 |
ATTENTION: the code below depends on being called by #raise or |
1609
21f69f2adef7
when skipping active handlers, must not only look for
Claus Gittinger <cg@exept.de>
parents:
1482
diff
changeset
|
727 |
#raiseRequest for proper operation (it skips the sending context)." |
1482
f4b65def90e1
oops - correctly look for handlers when exceptions
Claus Gittinger <cg@exept.de>
parents:
1378
diff
changeset
|
728 |
|
2562 | 729 |
|theContext block noHandlerSignal any msg conArg1 |
1710 | 730 |
theSignal c ex1 activeHandlers inHandler rejected |
3066 | 731 |
lastHandler h raiseReceiver r firstHandler| |
1482
f4b65def90e1
oops - correctly look for handlers when exceptions
Claus Gittinger <cg@exept.de>
parents:
1378
diff
changeset
|
732 |
|
3100 | 733 |
theSignal := signal. |
1482
f4b65def90e1
oops - correctly look for handlers when exceptions
Claus Gittinger <cg@exept.de>
parents:
1378
diff
changeset
|
734 |
theSignal isSignal ifFalse:[ |
2282 | 735 |
self halt:'unexpected non-Signal in calling context'. |
1482
f4b65def90e1
oops - correctly look for handlers when exceptions
Claus Gittinger <cg@exept.de>
parents:
1378
diff
changeset
|
736 |
]. |
171 | 737 |
|
1609
21f69f2adef7
when skipping active handlers, must not only look for
Claus Gittinger <cg@exept.de>
parents:
1482
diff
changeset
|
738 |
"/ 'search handler for: ' print. theSignal displayString printCR. |
21f69f2adef7
when skipping active handlers, must not only look for
Claus Gittinger <cg@exept.de>
parents:
1482
diff
changeset
|
739 |
|
1482
f4b65def90e1
oops - correctly look for handlers when exceptions
Claus Gittinger <cg@exept.de>
parents:
1378
diff
changeset
|
740 |
inHandler := false. |
3100 | 741 |
c := thisContext sender sender. "the raise/raiseRequest-context" |
742 |
"the signal raise context" |
|
1609
21f69f2adef7
when skipping active handlers, must not only look for
Claus Gittinger <cg@exept.de>
parents:
1482
diff
changeset
|
743 |
|
2204 | 744 |
"/ since the exceptionHandler is evaluated onTop of the |
745 |
"/ contextChain, we must skip active handlers before searching. |
|
746 |
"/ otherwise, we get into trouble, when re-raising an exception |
|
747 |
"/ from within a handler (which would lead to re-executing the |
|
748 |
"/ same handler) |
|
749 |
"/ the code below collects active handlers ... |
|
750 |
||
3066 | 751 |
"/ on the fly, look for the first #handle:do: - context, |
752 |
"/ and remember it (as firstHandler) to avoid walking the context chain twice |
|
753 |
"/ in most cases ... |
|
2291
af7652b82404
avoid touching contexts (making them nonLifo) when searching for unwind-contexts,
Claus Gittinger <cg@exept.de>
parents:
2282
diff
changeset
|
754 |
|
3066 | 755 |
firstHandler := nil. |
2208 | 756 |
|
3066 | 757 |
[c notNil] whileTrue:[ |
758 |
firstHandler isNil ifTrue:[ |
|
759 |
c := c findNextContextWithSelector:#doRaise or:#'handle:do:' or:#'handle:from:do:'. |
|
760 |
] ifFalse:[ |
|
761 |
c := c findNextContextWithSelector:#doRaise or:nil or:nil. |
|
762 |
]. |
|
763 |
c notNil ifTrue:[ |
|
764 |
(c selector == #doRaise) ifTrue:[ |
|
1609
21f69f2adef7
when skipping active handlers, must not only look for
Claus Gittinger <cg@exept.de>
parents:
1482
diff
changeset
|
765 |
|
3066 | 766 |
ex1 := c receiver. |
767 |
||
768 |
((ex1 class == self class) |
|
769 |
or:[ex1 species == self species]) ifTrue:[ |
|
3110 | 770 |
(ex1 signal == theSignal) ifTrue:[ |
771 |
h := ex1 handlerContext. |
|
772 |
h notNil ifTrue:[ |
|
773 |
r := h receiver. |
|
774 |
(r notNil and:[r accepts:theSignal]) ifTrue:[ |
|
775 |
activeHandlers isNil ifTrue:[ |
|
776 |
activeHandlers := OrderedCollection new |
|
777 |
]. |
|
2208 | 778 |
|
3110 | 779 |
lastHandler := h. |
780 |
activeHandlers add:lastHandler. |
|
781 |
inHandler := true. |
|
782 |
c := lastHandler. |
|
3066 | 783 |
] |
2282 | 784 |
] |
785 |
] |
|
786 |
] |
|
3066 | 787 |
] ifFalse:[ |
788 |
"/ must be a #handle:do context ... |
|
789 |
firstHandler := c. |
|
2291
af7652b82404
avoid touching contexts (making them nonLifo) when searching for unwind-contexts,
Claus Gittinger <cg@exept.de>
parents:
2282
diff
changeset
|
790 |
] |
2282 | 791 |
] |
1482
f4b65def90e1
oops - correctly look for handlers when exceptions
Claus Gittinger <cg@exept.de>
parents:
1378
diff
changeset
|
792 |
]. |
171 | 793 |
|
2208 | 794 |
"/ now, start searching for a handler, |
3066 | 795 |
"/ start search above the last active handler. |
796 |
"/ Or start with the first handle:do: context, if one |
|
797 |
"/ was found as a side effect of the previous handler search. |
|
798 |
"/ If nil, then there is no handler and we can directly proceed |
|
799 |
"/ to the unhandled code below. |
|
2208 | 800 |
|
1609
21f69f2adef7
when skipping active handlers, must not only look for
Claus Gittinger <cg@exept.de>
parents:
1482
diff
changeset
|
801 |
lastHandler notNil ifTrue:[ |
2291
af7652b82404
avoid touching contexts (making them nonLifo) when searching for unwind-contexts,
Claus Gittinger <cg@exept.de>
parents:
2282
diff
changeset
|
802 |
theContext := lastHandler. |
3066 | 803 |
theContext := lastHandler findNextContextWithSelector:#'handle:do:' or:#'handle:from:do:' or:nil. |
804 |
] ifFalse:[ |
|
805 |
theContext := firstHandler |
|
1609
21f69f2adef7
when skipping active handlers, must not only look for
Claus Gittinger <cg@exept.de>
parents:
1482
diff
changeset
|
806 |
]. |
21f69f2adef7
when skipping active handlers, must not only look for
Claus Gittinger <cg@exept.de>
parents:
1482
diff
changeset
|
807 |
|
3066 | 808 |
"/ remember if there was any handler |
809 |
"/ for the better errorString (unhandled vs. rejected exception) |
|
810 |
||
1482
f4b65def90e1
oops - correctly look for handlers when exceptions
Claus Gittinger <cg@exept.de>
parents:
1378
diff
changeset
|
811 |
any := false. |
2291
af7652b82404
avoid touching contexts (making them nonLifo) when searching for unwind-contexts,
Claus Gittinger <cg@exept.de>
parents:
2282
diff
changeset
|
812 |
[theContext notNil] whileTrue:[ |
3066 | 813 |
(theContext selector == #'handle:do:' |
814 |
or:[(theContext argAt:2) == originator]) |
|
815 |
ifTrue:[ |
|
816 |
(activeHandlers notNil |
|
817 |
and:[activeHandlers includesIdentical:theContext]) ifTrue:[ |
|
3068 | 818 |
"/ 'skip activeHandler: ' print. theContext displayString printCR. |
1482
f4b65def90e1
oops - correctly look for handlers when exceptions
Claus Gittinger <cg@exept.de>
parents:
1378
diff
changeset
|
819 |
|
3066 | 820 |
] ifFalse:[ |
821 |
" |
|
822 |
if this is the Signal>>handle:do: context |
|
823 |
or a SignalSet>>handle:do: context with self in it, |
|
824 |
call the handler |
|
825 |
" |
|
826 |
r := theContext receiver. |
|
827 |
(r notNil and:[r accepts:signal]) ifTrue:[ |
|
828 |
"call the handler" |
|
1482
f4b65def90e1
oops - correctly look for handlers when exceptions
Claus Gittinger <cg@exept.de>
parents:
1378
diff
changeset
|
829 |
|
3066 | 830 |
conArg1 := theContext argAt:1. |
1482
f4b65def90e1
oops - correctly look for handlers when exceptions
Claus Gittinger <cg@exept.de>
parents:
1378
diff
changeset
|
831 |
|
3066 | 832 |
handlerContext := theContext. |
833 |
any := true. |
|
1482
f4b65def90e1
oops - correctly look for handlers when exceptions
Claus Gittinger <cg@exept.de>
parents:
1378
diff
changeset
|
834 |
|
3066 | 835 |
self doCallHandler:conArg1. |
1482
f4b65def90e1
oops - correctly look for handlers when exceptions
Claus Gittinger <cg@exept.de>
parents:
1378
diff
changeset
|
836 |
|
3066 | 837 |
"/ if the handler rejects, we arrive here |
838 |
"/ continue search for another handler |
|
839 |
||
840 |
rejected := true. |
|
841 |
]. |
|
2291
af7652b82404
avoid touching contexts (making them nonLifo) when searching for unwind-contexts,
Claus Gittinger <cg@exept.de>
parents:
2282
diff
changeset
|
842 |
] |
3066 | 843 |
]. |
844 |
theContext := theContext findNextContextWithSelector:#'handle:do:' or:#'handle:from:do:' or:nil. |
|
1482
f4b65def90e1
oops - correctly look for handlers when exceptions
Claus Gittinger <cg@exept.de>
parents:
1378
diff
changeset
|
845 |
]. |
f4b65def90e1
oops - correctly look for handlers when exceptions
Claus Gittinger <cg@exept.de>
parents:
1378
diff
changeset
|
846 |
|
f4b65def90e1
oops - correctly look for handlers when exceptions
Claus Gittinger <cg@exept.de>
parents:
1378
diff
changeset
|
847 |
activeHandlers := nil. |
f4b65def90e1
oops - correctly look for handlers when exceptions
Claus Gittinger <cg@exept.de>
parents:
1378
diff
changeset
|
848 |
|
171 | 849 |
" |
850 |
we arrive here, if either no handler was found, or none of the |
|
851 |
handlers did a return (i.e. every handler rejected or fell through). |
|
852 |
" |
|
853 |
" |
|
854 |
try per signal handler |
|
855 |
" |
|
1038 | 856 |
(block := signal handlerBlock) isNil ifTrue:[ |
2282 | 857 |
"/ |
858 |
"/ if its a querySignal, ignore it |
|
859 |
"/ |
|
860 |
signal isQuerySignal ifTrue:[^ nil]. |
|
1118
1037616d9add
ignore unhandled querySignals
Claus Gittinger <cg@exept.de>
parents:
1038
diff
changeset
|
861 |
|
2282 | 862 |
"/ |
863 |
"/ if it is not the NoHandlerSignal, raise it ... |
|
864 |
"/ passing the receiver as parameter. |
|
865 |
"/ |
|
866 |
signal ~~ (noHandlerSignal := Signal noHandlerSignal) ifTrue:[ |
|
867 |
noHandlerSignal notNil ifTrue:[ |
|
868 |
any ifTrue:[ |
|
869 |
msg := 'unhandled (rejected)' |
|
870 |
] ifFalse:[ |
|
871 |
msg := 'unhandled' |
|
872 |
]. |
|
873 |
msg := msg , ' exception: (' , errorString , ')'. |
|
874 |
^ noHandlerSignal |
|
875 |
raiseRequestWith:self |
|
876 |
errorString:msg |
|
877 |
in:self suspendedContext |
|
878 |
]. |
|
879 |
"/ |
|
880 |
"/ mhmh - an error during early startup; noHandlerSignal is |
|
881 |
"/ not yet defined. |
|
882 |
"/ |
|
883 |
^ MiniDebugger enterWithMessage:errorString |
|
884 |
]. |
|
171 | 885 |
|
2282 | 886 |
" |
887 |
mhmh - smells like trouble - there is no handler and |
|
888 |
no per-signal handler block. |
|
889 |
Look for either a per-process emergencyHandlerBlock |
|
890 |
or the global emergencyHandler (from Exception) ... |
|
891 |
" |
|
892 |
Processor notNil ifTrue:[ |
|
893 |
"care for signal during startup (Processor not yet created)" |
|
894 |
block := Processor activeProcess emergencySignalHandler. |
|
895 |
]. |
|
896 |
block isNil ifTrue:[ |
|
897 |
block := Exception emergencyHandler. |
|
898 |
block isNil ifTrue:[ |
|
899 |
"care for error during startup (Exception not yet initialized)" |
|
900 |
^ MiniDebugger enterWithMessage:errorString |
|
901 |
]. |
|
902 |
]. |
|
171 | 903 |
]. |
904 |
"... and call it" |
|
905 |
^ block value:self. |
|
1118
1037616d9add
ignore unhandled querySignals
Claus Gittinger <cg@exept.de>
parents:
1038
diff
changeset
|
906 |
|
3066 | 907 |
"Created: / 12.5.1996 / 15:09:39 / cg" |
3100 | 908 |
"Modified: / 9.11.1997 / 14:48:44 / cg" |
1378
056b3a0928f2
oops - the last one was bogus
Claus Gittinger <cg@exept.de>
parents:
1376
diff
changeset
|
909 |
! |
056b3a0928f2
oops - the last one was bogus
Claus Gittinger <cg@exept.de>
parents:
1376
diff
changeset
|
910 |
|
056b3a0928f2
oops - the last one was bogus
Claus Gittinger <cg@exept.de>
parents:
1376
diff
changeset
|
911 |
raise |
056b3a0928f2
oops - the last one was bogus
Claus Gittinger <cg@exept.de>
parents:
1376
diff
changeset
|
912 |
"actually raise a non-proceedable exception. |
056b3a0928f2
oops - the last one was bogus
Claus Gittinger <cg@exept.de>
parents:
1376
diff
changeset
|
913 |
CAVEAT: |
2208 | 914 |
For now, in ST/X all signals are proceedable." |
1378
056b3a0928f2
oops - the last one was bogus
Claus Gittinger <cg@exept.de>
parents:
1376
diff
changeset
|
915 |
|
056b3a0928f2
oops - the last one was bogus
Claus Gittinger <cg@exept.de>
parents:
1376
diff
changeset
|
916 |
resumeBlock := [:value | ^ value]. |
056b3a0928f2
oops - the last one was bogus
Claus Gittinger <cg@exept.de>
parents:
1376
diff
changeset
|
917 |
^ self doRaise |
056b3a0928f2
oops - the last one was bogus
Claus Gittinger <cg@exept.de>
parents:
1376
diff
changeset
|
918 |
|
056b3a0928f2
oops - the last one was bogus
Claus Gittinger <cg@exept.de>
parents:
1376
diff
changeset
|
919 |
"Modified: 12.5.1996 / 15:09:47 / cg" |
1 | 920 |
! |
921 |
||
621 | 922 |
raiseRequest |
923 |
"actually raise a proceedable exception." |
|
1 | 924 |
|
1378
056b3a0928f2
oops - the last one was bogus
Claus Gittinger <cg@exept.de>
parents:
1376
diff
changeset
|
925 |
resumeBlock := [:value | ^ value]. |
056b3a0928f2
oops - the last one was bogus
Claus Gittinger <cg@exept.de>
parents:
1376
diff
changeset
|
926 |
^ self doRaise |
1376
6757590defbf
avoid extra send (raise->evaluateHandler)
Claus Gittinger <cg@exept.de>
parents:
1363
diff
changeset
|
927 |
|
1378
056b3a0928f2
oops - the last one was bogus
Claus Gittinger <cg@exept.de>
parents:
1376
diff
changeset
|
928 |
"Modified: 12.5.1996 / 15:09:44 / cg" |
621 | 929 |
! ! |
1 | 930 |
|
621 | 931 |
!Exception methodsFor:'setup'! |
1 | 932 |
|
621 | 933 |
signal:aSignal parameter:aParameter errorString:aString suspendedContext:sContext originator:origin |
934 |
"set the fields usable for inspection by the handler |
|
935 |
- only to be sent from the signal when raising" |
|
328 | 936 |
|
621 | 937 |
signal := aSignal. |
938 |
parameter := aParameter. |
|
939 |
errorString := aString. |
|
940 |
suspendedContext := sContext. |
|
941 |
originator := origin. |
|
942 |
! ! |
|
328 | 943 |
|
1953
c8a3af54acb3
unhandled querySignals should return nil
Claus Gittinger <cg@exept.de>
parents:
1710
diff
changeset
|
944 |
!Exception class methodsFor:'documentation'! |
662 | 945 |
|
946 |
version |
|
3111 | 947 |
^ '$Header: /cvs/stx/stx/libbasic/Exception.st,v 1.62 1997-11-15 14:06:12 cg Exp $' |
662 | 948 |
! ! |
621 | 949 |
Exception initialize! |