author | Claus Gittinger <cg@exept.de> |
Fri, 18 Apr 1997 16:39:43 +0200 | |
changeset 2562 | e89b40632edc |
parent 2509 | 20e70b07473a |
child 2893 | 8ba406da6b22 |
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 |
||
199 |
^ (self new) |
|
200 |
signal:aSignal |
|
201 |
parameter:aParameter |
|
202 |
errorString:aString |
|
203 |
suspendedContext:sContext |
|
204 |
originator:(sContext receiver). |
|
205 |
! |
|
206 |
||
207 |
signal:aSignal parameter:aParameter errorString:aString suspendedContext:sContext originator:origin |
|
208 |
"create a new instance and set the fields in preparation for a raise. |
|
209 |
- only to be sent from the signal when raising" |
|
210 |
||
211 |
^ (self new) |
|
212 |
signal:aSignal |
|
213 |
parameter:aParameter |
|
214 |
errorString:aString |
|
215 |
suspendedContext:sContext |
|
216 |
originator:origin. |
|
217 |
! ! |
|
218 |
||
1953
c8a3af54acb3
unhandled querySignals should return nil
Claus Gittinger <cg@exept.de>
parents:
1710
diff
changeset
|
219 |
!Exception class methodsFor:'Signal constants'! |
171 | 220 |
|
221 |
recursiveExceptionSignal |
|
222 |
"return the signal used to handle recursive signals in the handlers" |
|
223 |
||
224 |
^ RecursiveExceptionSignal |
|
225 |
! ! |
|
226 |
||
1953
c8a3af54acb3
unhandled querySignals should return nil
Claus Gittinger <cg@exept.de>
parents:
1710
diff
changeset
|
227 |
!Exception class methodsFor:'defaults'! |
12 | 228 |
|
229 |
emergencyHandler |
|
2174 | 230 |
"return the handler used for unhandled exceptions. |
231 |
||
232 |
If no EmergencyHandler has been set, a handler which enters the |
|
233 |
debugger is returned. |
|
234 |
The debugger is opened by asking the signal for a debug action, |
|
235 |
this allows to provide other debuggers in specialized (subclass-instances) |
|
236 |
of Signal (if that is ever needed)" |
|
12 | 237 |
|
77 | 238 |
" |
239 |
set it up, when called the first time |
|
240 |
" |
|
241 |
EmergencyHandler isNil ifTrue:[ |
|
2208 | 242 |
EmergencyHandler := [:ex | |
243 |
" |
|
244 |
sending it to the signal allows per-signal specific |
|
245 |
debuggers to be implemented in the future |
|
246 |
(for example, segv in primitive code could show things |
|
247 |
on the C-level ..) |
|
248 |
" |
|
249 |
(ex signal) enterDebuggerWith:ex message:(ex errorString). |
|
250 |
] |
|
77 | 251 |
]. |
252 |
||
12 | 253 |
^ EmergencyHandler |
2174 | 254 |
|
255 |
"Modified: 15.1.1997 / 20:50:37 / cg" |
|
12 | 256 |
! |
257 |
||
130 | 258 |
emergencyHandler:aOneArgBlock |
2174 | 259 |
"set the handler used for unhandled exceptions. |
260 |
The default (a nil-handler) leads to a debugger to be shown." |
|
12 | 261 |
|
130 | 262 |
EmergencyHandler := aOneArgBlock |
362 | 263 |
|
264 |
"ST-80 behavior of first showing a notifier: |
|
265 |
(I prefer to get right into the debugger, though) |
|
266 |
||
267 |
Exception |
|
2208 | 268 |
emergencyHandler: |
269 |
[:ex | self errorNotify:ex errorString ] |
|
2081 | 270 |
" |
271 |
||
272 |
"ST-X behavior of going right into the debugger: |
|
273 |
||
274 |
Exception |
|
2208 | 275 |
emergencyHandler:nil |
362 | 276 |
" |
277 |
||
278 |
"automatically aborting current operation, on error: |
|
279 |
(may be useful for end-user apps; make certain, |
|
280 |
you have abortSignal handlers at appropriate places) |
|
281 |
||
282 |
Exception |
|
2208 | 283 |
emergencyHandler: |
284 |
[:ex | Object abortSignal raise. ex return. ] |
|
362 | 285 |
" |
286 |
||
287 |
"finally, traditional language system behavior; dump core ;-) |
|
288 |
||
289 |
Exception |
|
2208 | 290 |
emergencyHandler: |
291 |
[:ex | Smalltalk exitWithCoreDump. ] |
|
362 | 292 |
" |
2081 | 293 |
|
2174 | 294 |
"Modified: 15.1.1997 / 20:49:06 / cg" |
295 |
! ! |
|
296 |
||
297 |
!Exception class methodsFor:'useful handlers'! |
|
298 |
||
299 |
abortingEmergencyHandler |
|
300 |
"return a block (usable as an emergency handler), |
|
301 |
which aborts after showing a warnBox. |
|
302 |
This is useful for endUser applications" |
|
303 |
||
304 |
^ [:ex | self warn:'Error: ' , ex errorString. |
|
2208 | 305 |
AbortSignal raise |
2174 | 306 |
] |
307 |
||
308 |
"test with (try a few halts or CTRL-C's): |
|
309 |
Exception emergencyHandler:(Exception abortingEmergencyHandler) |
|
310 |
" |
|
311 |
||
312 |
"back with: |
|
313 |
Exception emergencyHandler:(Exception notifyingEmergencyHandler) |
|
314 |
Exception emergencyHandler:nil |
|
315 |
" |
|
316 |
||
317 |
"Created: 15.1.1997 / 20:13:06 / cg" |
|
318 |
"Modified: 15.1.1997 / 20:15:02 / cg" |
|
319 |
! |
|
320 |
||
321 |
dumpingEmergencyHandler |
|
322 |
"return a block (usable as an emergency handler), |
|
323 |
which dumps the stackBacktrace to a trace file and |
|
324 |
aborts after showing a warnBox. |
|
325 |
This is useful, for endUser application, which are still being |
|
326 |
debugged (i.e. the programmers may have a look at the traceFile |
|
327 |
from time to time). |
|
328 |
||
329 |
Notice: |
|
2257 | 330 |
The code below is just an example; you may want to change the |
331 |
name of the error-file in your application |
|
332 |
(but please: copy the code; do not modify here)" |
|
2174 | 333 |
|
334 |
^ [:ex | |
|
2257 | 335 |
|str printedException| |
2174 | 336 |
|
2257 | 337 |
ex signal == Signal noHandlerSignal ifTrue:[ |
338 |
printedException := ex parameter. |
|
339 |
] ifFalse:[ |
|
340 |
printedException := ex |
|
341 |
]. |
|
342 |
||
343 |
"/ user interruption is handled specially: |
|
344 |
"/ allow user to choose between proceeding or aborting |
|
345 |
"/ but never dump that information to the file. |
|
2174 | 346 |
|
2257 | 347 |
printedException signal == Object userInterruptSignal ifTrue:[ |
348 |
(self confirm:'abort current action ?') ifTrue:[ |
|
349 |
AbortSignal raise |
|
350 |
]. |
|
351 |
ex proceed |
|
352 |
]. |
|
2174 | 353 |
|
2257 | 354 |
"/ |
355 |
"/ dump it to 'errorTrace.stx' |
|
356 |
"/ |
|
357 |
str := 'errorTrace.stx' asFilename appendingWriteStream. |
|
2174 | 358 |
|
2257 | 359 |
str nextPutLine:('******************************* ' |
360 |
, AbsoluteTime now printString |
|
361 |
, ' *******************************'). |
|
362 |
str cr. |
|
2174 | 363 |
|
2257 | 364 |
str nextPutLine:('** Error: ' , printedException errorString). |
365 |
str nextPutLine:('** Signal: ' , printedException signal printString). |
|
366 |
str nextPutLine:('** Parameter: ' , printedException parameter printString). |
|
367 |
str nextPutLine:('** Process: ' , Processor activeProcess printString). |
|
368 |
str nextPutLine:('** Backtrace:'). |
|
369 |
str cr. |
|
2174 | 370 |
|
2257 | 371 |
printedException suspendedContext fullPrintAllOn:str. |
372 |
str cr. |
|
373 |
str cr. |
|
374 |
str close. |
|
2174 | 375 |
|
2257 | 376 |
"/ send a line to stdErr |
377 |
||
378 |
('[warning]: ignored error: ' , printedException errorString) errorPrintCR. |
|
379 |
('[warning]: error information appended to ''errorTrace.stx''') errorPrintCR. |
|
380 |
||
381 |
AbortSignal raise |
|
2174 | 382 |
] |
383 |
||
384 |
"test with (try a few halts or CTRL-C's): |
|
385 |
Exception emergencyHandler:(Exception dumpingEmergencyHandler) |
|
386 |
" |
|
387 |
||
388 |
"back with: |
|
389 |
Exception emergencyHandler:(Exception notifyingEmergencyHandler) |
|
390 |
Exception emergencyHandler:nil |
|
391 |
" |
|
392 |
||
393 |
"Created: 15.1.1997 / 20:14:52 / cg" |
|
2257 | 394 |
"Modified: 24.1.1997 / 20:36:21 / cg" |
2174 | 395 |
! |
396 |
||
397 |
mailingEmergencyHandler |
|
398 |
"return a block (usable as an emergency handler), |
|
399 |
which shows a warnBox and optionally mails a stackBacktrace to a maintainer. |
|
400 |
This is useful, for endUser application, which are still being |
|
401 |
debugged (i.e. the programmers may have a look at the errors). |
|
402 |
||
403 |
Notice: the stuff here is a demonstration only; it should be modified |
|
2208 | 404 |
for your particular environment ... |
405 |
... but please: copy the code and modify there; |
|
406 |
leave the stuff below as it is." |
|
2174 | 407 |
|
408 |
^ [:ex | |
|
2208 | 409 |
|str printedException doMail emergencyMailReceiver pipe| |
2174 | 410 |
|
2208 | 411 |
ex signal == Signal noHandlerSignal ifTrue:[ |
412 |
printedException := ex parameter. |
|
413 |
] ifFalse:[ |
|
414 |
printedException := ex |
|
415 |
]. |
|
2174 | 416 |
|
2208 | 417 |
"/ user interruption is handled specially: |
418 |
"/ allow user to choose between proceeding or aborting |
|
419 |
"/ but never dump that information to the file. |
|
2174 | 420 |
|
2208 | 421 |
printedException signal == Object userInterruptSignal ifTrue:[ |
422 |
(self confirm:'abort current action ?') ifTrue:[ |
|
423 |
AbortSignal raise |
|
424 |
]. |
|
425 |
ex proceed |
|
426 |
]. |
|
2174 | 427 |
|
2208 | 428 |
"/ somehow get the name of the guy to receive the mail |
429 |
"/ you have to implement that yourself. |
|
2174 | 430 |
|
2208 | 431 |
"/ emergencyMailReceiver := OneOfYourClass getEmergencyMailReceiver. |
432 |
emergencyMailReceiver := OperatingSystem getLoginName. |
|
2174 | 433 |
|
2208 | 434 |
emergencyMailReceiver isNil ifTrue:[ |
435 |
self warn:(printedException errorString |
|
436 |
, '\\No mailing to service people possible.') withCRs. |
|
437 |
doMail := false. |
|
438 |
] ifFalse:[ |
|
439 |
doMail := self confirm:(printedException errorString |
|
440 |
, '\\Mail error information to the service people (' |
|
441 |
, emergencyMailReceiver , ') ?') withCRs |
|
442 |
]. |
|
443 |
doMail ifTrue:[ |
|
444 |
str := '' writeStream. |
|
2174 | 445 |
|
2208 | 446 |
str nextPutLine:('Error notification from ' |
447 |
, OperatingSystem getLoginName |
|
448 |
, '@' |
|
449 |
, OperatingSystem getHostName). |
|
450 |
str cr. |
|
2174 | 451 |
|
2208 | 452 |
str nextPutLine:('Time: ' , AbsoluteTime now printString). |
453 |
str nextPutLine:('Error: ', printedException errorString). |
|
454 |
str nextPutLine:('Signal: ', printedException signal printString). |
|
455 |
str nextPutLine:('Parameter: ', printedException parameter printString). |
|
456 |
str nextPutLine:('Process: ', Processor activeProcess printString). |
|
457 |
str nextPutLine:'Backtrace:'. |
|
458 |
str cr. |
|
2174 | 459 |
|
2208 | 460 |
printedException suspendedContext fullPrintAllOn:str. |
461 |
str cr;cr. |
|
2174 | 462 |
|
2208 | 463 |
str close. |
2174 | 464 |
|
2208 | 465 |
pipe := PipeStream |
466 |
writingTo:'mail ', emergencyMailReceiver. |
|
467 |
pipe notNil ifTrue:[ |
|
468 |
pipe nextPutLine:'Subject: automatic error report'. |
|
469 |
pipe nextPutAll:str contents. |
|
470 |
pipe cr. |
|
471 |
pipe close. |
|
472 |
] |
|
473 |
]. |
|
2174 | 474 |
|
2208 | 475 |
AbortSignal raise |
2174 | 476 |
] |
477 |
||
478 |
"test with (try a few halts or CTRL-C's): |
|
479 |
Exception emergencyHandler:(Exception mailingEmergencyHandler) |
|
480 |
" |
|
481 |
||
482 |
"back with: |
|
483 |
Exception emergencyHandler:(Exception notifyingEmergencyHandler) |
|
484 |
Exception emergencyHandler:nil |
|
485 |
" |
|
486 |
||
487 |
"Created: 15.1.1997 / 20:14:52 / cg" |
|
488 |
"Modified: 15.1.1997 / 21:10:28 / cg" |
|
489 |
! |
|
490 |
||
491 |
notifyingEmergencyHandler |
|
492 |
"return a block (usable as an emergency handler for exceptions), |
|
493 |
which does errorNotification before going into the debugger." |
|
494 |
||
495 |
^ [:ex | nil errorNotify:ex errorString from:ex suspendedContext ] |
|
496 |
||
497 |
"test with (try a few halts or CTRL-C's): |
|
498 |
Exception emergencyHandler:(Exception notifyingEmergencyHandler) |
|
499 |
" |
|
500 |
||
501 |
"back with: |
|
502 |
Exception emergencyHandler:nil |
|
503 |
" |
|
504 |
||
505 |
"Modified: 15.1.1997 / 20:15:12 / cg" |
|
362 | 506 |
! ! |
507 |
||
1 | 508 |
!Exception methodsFor:'accessing'! |
509 |
||
44 | 510 |
errorString |
511 |
"return the errorString passsed with the signal raise |
|
512 |
(or nil, if there was none)" |
|
513 |
||
514 |
^ errorString |
|
515 |
! |
|
516 |
||
621 | 517 |
handlerContext |
518 |
"return the context of the handler" |
|
519 |
||
520 |
^ handlerContext |
|
521 |
! |
|
522 |
||
362 | 523 |
originator |
524 |
"return the originator passsed with the signal raise |
|
525 |
(or nil, if there was none)" |
|
526 |
||
527 |
^ originator |
|
528 |
! |
|
529 |
||
621 | 530 |
parameter |
531 |
"return the parameter passsed with the signal raise |
|
532 |
(or nil, if there was none)" |
|
44 | 533 |
|
621 | 534 |
^ parameter |
68 | 535 |
! |
536 |
||
537 |
rejected |
|
362 | 538 |
"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
|
539 |
Uncertain, if this is really interesting to anybody. |
362 | 540 |
This is only valid during handler execution. |
541 |
(i.e. an outer handler can find out, if any other handler has already |
|
542 |
rejected). |
|
543 |
" |
|
68 | 544 |
|
545 |
^ rejected |
|
362 | 546 |
! |
547 |
||
621 | 548 |
signal |
549 |
"return the signal, that caused the exception" |
|
550 |
||
551 |
^ signal |
|
552 |
! |
|
553 |
||
554 |
suspendedContext |
|
555 |
"return the context in which the raise occured" |
|
556 |
||
557 |
^ suspendedContext |
|
558 |
! |
|
559 |
||
362 | 560 |
willProceed |
561 |
"return true, if the exception is proceedable" |
|
562 |
||
563 |
^ resumeBlock notNil |
|
1 | 564 |
! ! |
565 |
||
621 | 566 |
!Exception methodsFor:'handler actions'! |
567 |
||
568 |
proceed |
|
569 |
"Continue after the raise - the raise returns nil" |
|
570 |
||
2509
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
571 |
|b| |
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
572 |
|
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
573 |
resumeBlock notNil ifTrue:[ |
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
574 |
b := resumeBlock. |
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
575 |
resumeBlock := rejectBlock := handlerContext := suspendedContext := nil. |
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
576 |
b value:nil |
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
577 |
] |
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
578 |
|
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
579 |
"Modified: 27.3.1997 / 16:44:39 / cg" |
621 | 580 |
! |
581 |
||
582 |
proceedWith:value |
|
583 |
"Continue after the raise - the raise returns value" |
|
584 |
||
2509
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
585 |
|b| |
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
586 |
|
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
587 |
resumeBlock notNil ifTrue:[ |
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
588 |
b := resumeBlock. |
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
589 |
resumeBlock := rejectBlock := handlerContext := suspendedContext := nil. |
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
590 |
b value:value |
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
591 |
] |
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
592 |
|
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
593 |
"Modified: 27.3.1997 / 16:45:57 / cg" |
621 | 594 |
! |
1 | 595 |
|
621 | 596 |
reject |
597 |
"handler decided not to handle this signal - |
|
598 |
system will look for another handler" |
|
599 |
||
600 |
rejected := true. |
|
601 |
rejectBlock value |
|
602 |
! |
|
603 |
||
604 |
restart |
|
605 |
"restart the handle:do: - usually after some repair work is done |
|
606 |
in handler" |
|
607 |
||
608 |
handlerContext unwindAndRestart |
|
609 |
! |
|
1 | 610 |
|
621 | 611 |
resume |
612 |
"Continue after the raise - the raise returns nil" |
|
613 |
||
2509
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
614 |
|b| |
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
615 |
|
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
616 |
resumeBlock notNil ifTrue:[ |
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
617 |
b := resumeBlock. |
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
618 |
resumeBlock := rejectBlock := handlerContext := suspendedContext := nil. |
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
619 |
b value:nil |
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
620 |
] |
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
621 |
|
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
622 |
"Modified: 27.3.1997 / 16:45:18 / cg" |
621 | 623 |
! |
624 |
||
625 |
resumeWith:value |
|
626 |
"Continue after the raise - the raise returns value" |
|
627 |
||
2509
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
628 |
|b| |
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
629 |
|
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
630 |
resumeBlock notNil ifTrue:[ |
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
631 |
b := resumeBlock. |
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
632 |
resumeBlock := rejectBlock := handlerContext := suspendedContext := nil. |
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
633 |
b value:value |
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
634 |
] |
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
635 |
|
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
636 |
"Modified: 27.3.1997 / 16:45:41 / cg" |
621 | 637 |
! |
638 |
||
639 |
return |
|
640 |
"Continue after the handle:do: - the handle:do: returns nil" |
|
641 |
||
2509
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
642 |
|con| |
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
643 |
|
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
644 |
con := handlerContext. |
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
645 |
resumeBlock := rejectBlock := handlerContext := suspendedContext := nil. |
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
646 |
con unwind |
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
647 |
|
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
648 |
"Modified: 27.3.1997 / 16:46:39 / cg" |
621 | 649 |
! |
650 |
||
651 |
returnDoing:aBlock |
|
652 |
"Continue after the handle:do: - the handle:do: returns aBlock value" |
|
653 |
||
654 |
handlerContext unwindThenDo:aBlock |
|
655 |
! |
|
656 |
||
657 |
returnWith:value |
|
658 |
"Continue after the handle:do: - the handle:do: returns value" |
|
659 |
||
2509
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
660 |
|con| |
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
661 |
|
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
662 |
con := handlerContext. |
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
663 |
resumeBlock := rejectBlock := handlerContext := suspendedContext := nil. |
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
664 |
con unwind:value |
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
665 |
|
20e70b07473a
clean out exceptions block & context references when
Claus Gittinger <cg@exept.de>
parents:
2433
diff
changeset
|
666 |
"Modified: 27.3.1997 / 16:46:51 / cg" |
171 | 667 |
! ! |
668 |
||
217 | 669 |
!Exception methodsFor:'raising'! |
1 | 670 |
|
621 | 671 |
doCallHandler:aHandler |
672 |
"call the handler proper - needed an extra method |
|
673 |
to have a separate returnContext for the rejectBlock. |
|
674 |
(which is historical, and actually no longer needed)" |
|
675 |
||
676 |
|val| |
|
362 | 677 |
|
621 | 678 |
rejectBlock := [^ self]. "this will return on reject" |
679 |
val := aHandler value:self. |
|
680 |
" |
|
681 |
handler fall through - is just like a returnWith:blocks-value |
|
682 |
" |
|
2291
af7652b82404
avoid touching contexts (making them nonLifo) when searching for unwind-contexts,
Claus Gittinger <cg@exept.de>
parents:
2282
diff
changeset
|
683 |
rejectBlock := nil. |
621 | 684 |
self returnWith:val |
1 | 685 |
! |
686 |
||
1378
056b3a0928f2
oops - the last one was bogus
Claus Gittinger <cg@exept.de>
parents:
1376
diff
changeset
|
687 |
doRaise |
171 | 688 |
"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
|
689 |
to the raising signal, a parent of it, or a SignalSet which includes |
171 | 690 |
the raising signal. |
691 |
If found, take the contexts 2nd argument (the handler) and evaluate |
|
692 |
it with the receiver exception as argument. |
|
217 | 693 |
If no handler is found, try per signal handler, or |
694 |
per process handler (if its the noHandlerSignal). |
|
695 |
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
|
696 |
available and enters the debugger. |
f4b65def90e1
oops - correctly look for handlers when exceptions
Claus Gittinger <cg@exept.de>
parents:
1378
diff
changeset
|
697 |
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
|
698 |
#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
|
699 |
|
2562 | 700 |
|theContext block noHandlerSignal any msg conArg1 |
1710 | 701 |
theSignal c ex1 activeHandlers inHandler rejected |
2208 | 702 |
lastHandler h raiseReceiver| |
1482
f4b65def90e1
oops - correctly look for handlers when exceptions
Claus Gittinger <cg@exept.de>
parents:
1378
diff
changeset
|
703 |
|
2433 | 704 |
theContext := thisContext sender sender. "the raise/raiseRequest-context" |
705 |
"the signal raise context" |
|
1482
f4b65def90e1
oops - correctly look for handlers when exceptions
Claus Gittinger <cg@exept.de>
parents:
1378
diff
changeset
|
706 |
|
2291
af7652b82404
avoid touching contexts (making them nonLifo) when searching for unwind-contexts,
Claus Gittinger <cg@exept.de>
parents:
2282
diff
changeset
|
707 |
theSignal := theContext receiver. |
1482
f4b65def90e1
oops - correctly look for handlers when exceptions
Claus Gittinger <cg@exept.de>
parents:
1378
diff
changeset
|
708 |
theSignal isSignal ifFalse:[ |
2282 | 709 |
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
|
710 |
]. |
171 | 711 |
|
1609
21f69f2adef7
when skipping active handlers, must not only look for
Claus Gittinger <cg@exept.de>
parents:
1482
diff
changeset
|
712 |
"/ '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
|
713 |
|
1482
f4b65def90e1
oops - correctly look for handlers when exceptions
Claus Gittinger <cg@exept.de>
parents:
1378
diff
changeset
|
714 |
inHandler := false. |
2291
af7652b82404
avoid touching contexts (making them nonLifo) when searching for unwind-contexts,
Claus Gittinger <cg@exept.de>
parents:
2282
diff
changeset
|
715 |
c := theContext. |
1609
21f69f2adef7
when skipping active handlers, must not only look for
Claus Gittinger <cg@exept.de>
parents:
1482
diff
changeset
|
716 |
|
2204 | 717 |
"/ since the exceptionHandler is evaluated onTop of the |
718 |
"/ contextChain, we must skip active handlers before searching. |
|
719 |
"/ otherwise, we get into trouble, when re-raising an exception |
|
720 |
"/ from within a handler (which would lead to re-executing the |
|
721 |
"/ same handler) |
|
722 |
"/ the code below collects active handlers ... |
|
723 |
||
1482
f4b65def90e1
oops - correctly look for handlers when exceptions
Claus Gittinger <cg@exept.de>
parents:
1378
diff
changeset
|
724 |
[c notNil] whileTrue:[ |
2291
af7652b82404
avoid touching contexts (making them nonLifo) when searching for unwind-contexts,
Claus Gittinger <cg@exept.de>
parents:
2282
diff
changeset
|
725 |
c := c findNextContextWithSelector:#doRaise or:nil. |
2282 | 726 |
c notNil ifTrue:[ |
2208 | 727 |
|
2282 | 728 |
ex1 := c receiver. |
2291
af7652b82404
avoid touching contexts (making them nonLifo) when searching for unwind-contexts,
Claus Gittinger <cg@exept.de>
parents:
2282
diff
changeset
|
729 |
|
2282 | 730 |
((ex1 class == self class) |
731 |
or:[ex1 species == self species]) ifTrue:[ |
|
732 |
c := c sender. |
|
733 |
(c notNil and:[c receiver == ex1]) ifTrue:[ |
|
734 |
c := c sender. |
|
735 |
c notNil ifTrue:[ |
|
2208 | 736 |
|
2282 | 737 |
"/ the common case (really ?) first |
738 |
((raiseReceiver := c receiver) == theSignal) ifTrue:[ |
|
739 |
(c selector startsWith:'raise') ifTrue:[ |
|
740 |
h := ex1 handlerContext. |
|
741 |
h notNil ifTrue:[ |
|
742 |
activeHandlers isNil ifTrue:[ |
|
743 |
activeHandlers := OrderedCollection new |
|
744 |
]. |
|
1609
21f69f2adef7
when skipping active handlers, must not only look for
Claus Gittinger <cg@exept.de>
parents:
1482
diff
changeset
|
745 |
|
2282 | 746 |
lastHandler := h. |
747 |
activeHandlers add:lastHandler. |
|
748 |
inHandler := true. |
|
749 |
c := lastHandler. |
|
750 |
] |
|
751 |
] |
|
752 |
] ifFalse:[ |
|
753 |
raiseReceiver isSignal ifTrue:[ |
|
754 |
(c selector startsWith:'raise') ifTrue:[ |
|
755 |
h := ex1 handlerContext. |
|
756 |
h notNil ifTrue:[ |
|
757 |
(h receiver accepts:theSignal) ifTrue:[ |
|
2208 | 758 |
|
2282 | 759 |
activeHandlers isNil ifTrue:[ |
760 |
activeHandlers := OrderedCollection new |
|
761 |
]. |
|
762 |
lastHandler := h. |
|
763 |
activeHandlers add:lastHandler. |
|
764 |
inHandler := true. |
|
765 |
c := lastHandler. |
|
766 |
] |
|
767 |
] |
|
768 |
] |
|
769 |
] |
|
770 |
] |
|
771 |
] |
|
772 |
] |
|
2291
af7652b82404
avoid touching contexts (making them nonLifo) when searching for unwind-contexts,
Claus Gittinger <cg@exept.de>
parents:
2282
diff
changeset
|
773 |
] |
2282 | 774 |
] |
1482
f4b65def90e1
oops - correctly look for handlers when exceptions
Claus Gittinger <cg@exept.de>
parents:
1378
diff
changeset
|
775 |
]. |
171 | 776 |
|
2208 | 777 |
"/ now, start searching for a handler, |
778 |
"/ start search above the last active handler |
|
779 |
||
1609
21f69f2adef7
when skipping active handlers, must not only look for
Claus Gittinger <cg@exept.de>
parents:
1482
diff
changeset
|
780 |
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
|
781 |
theContext := lastHandler. |
1609
21f69f2adef7
when skipping active handlers, must not only look for
Claus Gittinger <cg@exept.de>
parents:
1482
diff
changeset
|
782 |
]. |
21f69f2adef7
when skipping active handlers, must not only look for
Claus Gittinger <cg@exept.de>
parents:
1482
diff
changeset
|
783 |
|
1482
f4b65def90e1
oops - correctly look for handlers when exceptions
Claus Gittinger <cg@exept.de>
parents:
1378
diff
changeset
|
784 |
any := false. |
2291
af7652b82404
avoid touching contexts (making them nonLifo) when searching for unwind-contexts,
Claus Gittinger <cg@exept.de>
parents:
2282
diff
changeset
|
785 |
[theContext notNil] whileTrue:[ |
af7652b82404
avoid touching contexts (making them nonLifo) when searching for unwind-contexts,
Claus Gittinger <cg@exept.de>
parents:
2282
diff
changeset
|
786 |
theContext := theContext findNextContextWithSelector:#'handle:do:' or:#'handle:from:do:'. |
af7652b82404
avoid touching contexts (making them nonLifo) when searching for unwind-contexts,
Claus Gittinger <cg@exept.de>
parents:
2282
diff
changeset
|
787 |
theContext notNil ifTrue:[ |
af7652b82404
avoid touching contexts (making them nonLifo) when searching for unwind-contexts,
Claus Gittinger <cg@exept.de>
parents:
2282
diff
changeset
|
788 |
(theContext selector == #'handle:do:' |
2562 | 789 |
or:[(theContext argAt:2) == originator]) |
790 |
ifTrue:[ |
|
2282 | 791 |
(activeHandlers notNil |
2291
af7652b82404
avoid touching contexts (making them nonLifo) when searching for unwind-contexts,
Claus Gittinger <cg@exept.de>
parents:
2282
diff
changeset
|
792 |
and:[activeHandlers includesIdentical:theContext]) ifTrue:[ |
af7652b82404
avoid touching contexts (making them nonLifo) when searching for unwind-contexts,
Claus Gittinger <cg@exept.de>
parents:
2282
diff
changeset
|
793 |
'skip activeHandler: ' print. theContext displayString printCR. |
1482
f4b65def90e1
oops - correctly look for handlers when exceptions
Claus Gittinger <cg@exept.de>
parents:
1378
diff
changeset
|
794 |
|
2282 | 795 |
] ifFalse:[ |
796 |
" |
|
797 |
if this is the Signal>>handle:do: context |
|
798 |
or a SignalSet>>handle:do: context with self in it, |
|
799 |
call the handler |
|
800 |
" |
|
2291
af7652b82404
avoid touching contexts (making them nonLifo) when searching for unwind-contexts,
Claus Gittinger <cg@exept.de>
parents:
2282
diff
changeset
|
801 |
(theContext receiver accepts:signal) ifTrue:[ |
2282 | 802 |
"call the handler" |
1482
f4b65def90e1
oops - correctly look for handlers when exceptions
Claus Gittinger <cg@exept.de>
parents:
1378
diff
changeset
|
803 |
|
2291
af7652b82404
avoid touching contexts (making them nonLifo) when searching for unwind-contexts,
Claus Gittinger <cg@exept.de>
parents:
2282
diff
changeset
|
804 |
conArg1 := theContext argAt:1. |
1482
f4b65def90e1
oops - correctly look for handlers when exceptions
Claus Gittinger <cg@exept.de>
parents:
1378
diff
changeset
|
805 |
|
2291
af7652b82404
avoid touching contexts (making them nonLifo) when searching for unwind-contexts,
Claus Gittinger <cg@exept.de>
parents:
2282
diff
changeset
|
806 |
handlerContext := theContext. |
2282 | 807 |
any := true. |
1482
f4b65def90e1
oops - correctly look for handlers when exceptions
Claus Gittinger <cg@exept.de>
parents:
1378
diff
changeset
|
808 |
|
2282 | 809 |
self doCallHandler:conArg1. |
1482
f4b65def90e1
oops - correctly look for handlers when exceptions
Claus Gittinger <cg@exept.de>
parents:
1378
diff
changeset
|
810 |
|
2282 | 811 |
"if the handler rejects, we arrive here" |
812 |
"continue search for another handler" |
|
813 |
rejected := true. |
|
814 |
]. |
|
815 |
] |
|
2291
af7652b82404
avoid touching contexts (making them nonLifo) when searching for unwind-contexts,
Claus Gittinger <cg@exept.de>
parents:
2282
diff
changeset
|
816 |
] |
af7652b82404
avoid touching contexts (making them nonLifo) when searching for unwind-contexts,
Claus Gittinger <cg@exept.de>
parents:
2282
diff
changeset
|
817 |
] |
1482
f4b65def90e1
oops - correctly look for handlers when exceptions
Claus Gittinger <cg@exept.de>
parents:
1378
diff
changeset
|
818 |
]. |
f4b65def90e1
oops - correctly look for handlers when exceptions
Claus Gittinger <cg@exept.de>
parents:
1378
diff
changeset
|
819 |
|
f4b65def90e1
oops - correctly look for handlers when exceptions
Claus Gittinger <cg@exept.de>
parents:
1378
diff
changeset
|
820 |
activeHandlers := nil. |
f4b65def90e1
oops - correctly look for handlers when exceptions
Claus Gittinger <cg@exept.de>
parents:
1378
diff
changeset
|
821 |
|
171 | 822 |
" |
823 |
we arrive here, if either no handler was found, or none of the |
|
824 |
handlers did a return (i.e. every handler rejected or fell through). |
|
825 |
" |
|
826 |
" |
|
827 |
try per signal handler |
|
828 |
" |
|
1038 | 829 |
(block := signal handlerBlock) isNil ifTrue:[ |
2282 | 830 |
"/ |
831 |
"/ if its a querySignal, ignore it |
|
832 |
"/ |
|
833 |
signal isQuerySignal ifTrue:[^ nil]. |
|
1118
1037616d9add
ignore unhandled querySignals
Claus Gittinger <cg@exept.de>
parents:
1038
diff
changeset
|
834 |
|
2282 | 835 |
"/ |
836 |
"/ if it is not the NoHandlerSignal, raise it ... |
|
837 |
"/ passing the receiver as parameter. |
|
838 |
"/ |
|
839 |
signal ~~ (noHandlerSignal := Signal noHandlerSignal) ifTrue:[ |
|
840 |
noHandlerSignal notNil ifTrue:[ |
|
841 |
any ifTrue:[ |
|
842 |
msg := 'unhandled (rejected)' |
|
843 |
] ifFalse:[ |
|
844 |
msg := 'unhandled' |
|
845 |
]. |
|
846 |
msg := msg , ' exception: (' , errorString , ')'. |
|
847 |
^ noHandlerSignal |
|
848 |
raiseRequestWith:self |
|
849 |
errorString:msg |
|
850 |
in:self suspendedContext |
|
851 |
]. |
|
852 |
"/ |
|
853 |
"/ mhmh - an error during early startup; noHandlerSignal is |
|
854 |
"/ not yet defined. |
|
855 |
"/ |
|
856 |
^ MiniDebugger enterWithMessage:errorString |
|
857 |
]. |
|
171 | 858 |
|
2282 | 859 |
" |
860 |
mhmh - smells like trouble - there is no handler and |
|
861 |
no per-signal handler block. |
|
862 |
Look for either a per-process emergencyHandlerBlock |
|
863 |
or the global emergencyHandler (from Exception) ... |
|
864 |
" |
|
865 |
Processor notNil ifTrue:[ |
|
866 |
"care for signal during startup (Processor not yet created)" |
|
867 |
block := Processor activeProcess emergencySignalHandler. |
|
868 |
]. |
|
869 |
block isNil ifTrue:[ |
|
870 |
block := Exception emergencyHandler. |
|
871 |
block isNil ifTrue:[ |
|
872 |
"care for error during startup (Exception not yet initialized)" |
|
873 |
^ MiniDebugger enterWithMessage:errorString |
|
874 |
]. |
|
875 |
]. |
|
171 | 876 |
]. |
877 |
"... and call it" |
|
878 |
^ block value:self. |
|
1118
1037616d9add
ignore unhandled querySignals
Claus Gittinger <cg@exept.de>
parents:
1038
diff
changeset
|
879 |
|
1378
056b3a0928f2
oops - the last one was bogus
Claus Gittinger <cg@exept.de>
parents:
1376
diff
changeset
|
880 |
"Created: 12.5.1996 / 15:09:39 / cg" |
2433 | 881 |
"Modified: 1.3.1997 / 23:53:14 / cg" |
1378
056b3a0928f2
oops - the last one was bogus
Claus Gittinger <cg@exept.de>
parents:
1376
diff
changeset
|
882 |
! |
056b3a0928f2
oops - the last one was bogus
Claus Gittinger <cg@exept.de>
parents:
1376
diff
changeset
|
883 |
|
056b3a0928f2
oops - the last one was bogus
Claus Gittinger <cg@exept.de>
parents:
1376
diff
changeset
|
884 |
raise |
056b3a0928f2
oops - the last one was bogus
Claus Gittinger <cg@exept.de>
parents:
1376
diff
changeset
|
885 |
"actually raise a non-proceedable exception. |
056b3a0928f2
oops - the last one was bogus
Claus Gittinger <cg@exept.de>
parents:
1376
diff
changeset
|
886 |
CAVEAT: |
2208 | 887 |
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
|
888 |
|
056b3a0928f2
oops - the last one was bogus
Claus Gittinger <cg@exept.de>
parents:
1376
diff
changeset
|
889 |
resumeBlock := [:value | ^ value]. |
056b3a0928f2
oops - the last one was bogus
Claus Gittinger <cg@exept.de>
parents:
1376
diff
changeset
|
890 |
^ self doRaise |
056b3a0928f2
oops - the last one was bogus
Claus Gittinger <cg@exept.de>
parents:
1376
diff
changeset
|
891 |
|
056b3a0928f2
oops - the last one was bogus
Claus Gittinger <cg@exept.de>
parents:
1376
diff
changeset
|
892 |
"Modified: 12.5.1996 / 15:09:47 / cg" |
1 | 893 |
! |
894 |
||
621 | 895 |
raiseRequest |
896 |
"actually raise a proceedable exception." |
|
1 | 897 |
|
1378
056b3a0928f2
oops - the last one was bogus
Claus Gittinger <cg@exept.de>
parents:
1376
diff
changeset
|
898 |
resumeBlock := [:value | ^ value]. |
056b3a0928f2
oops - the last one was bogus
Claus Gittinger <cg@exept.de>
parents:
1376
diff
changeset
|
899 |
^ self doRaise |
1376
6757590defbf
avoid extra send (raise->evaluateHandler)
Claus Gittinger <cg@exept.de>
parents:
1363
diff
changeset
|
900 |
|
1378
056b3a0928f2
oops - the last one was bogus
Claus Gittinger <cg@exept.de>
parents:
1376
diff
changeset
|
901 |
"Modified: 12.5.1996 / 15:09:44 / cg" |
621 | 902 |
! ! |
1 | 903 |
|
621 | 904 |
!Exception methodsFor:'setup'! |
1 | 905 |
|
621 | 906 |
signal:aSignal parameter:aParameter errorString:aString suspendedContext:sContext originator:origin |
907 |
"set the fields usable for inspection by the handler |
|
908 |
- only to be sent from the signal when raising" |
|
328 | 909 |
|
621 | 910 |
signal := aSignal. |
911 |
parameter := aParameter. |
|
912 |
errorString := aString. |
|
913 |
suspendedContext := sContext. |
|
914 |
originator := origin. |
|
915 |
! ! |
|
328 | 916 |
|
1953
c8a3af54acb3
unhandled querySignals should return nil
Claus Gittinger <cg@exept.de>
parents:
1710
diff
changeset
|
917 |
!Exception class methodsFor:'documentation'! |
662 | 918 |
|
919 |
version |
|
2562 | 920 |
^ '$Header: /cvs/stx/stx/libbasic/Exception.st,v 1.53 1997-04-18 14:39:43 cg Exp $' |
662 | 921 |
! ! |
621 | 922 |
Exception initialize! |