Exception.st
changeset 4464 cec93c942c14
parent 4449 c8e195e21aab
child 4466 9cba6f4ecec4
equal deleted inserted replaced
4463:60cc202629e2 4464:cec93c942c14
     8  be provided or otherwise made available to, or used by, any
     8  be provided or otherwise made available to, or used by, any
     9  other person.  No title to or ownership of the software is
     9  other person.  No title to or ownership of the software is
    10  hereby transferred.
    10  hereby transferred.
    11 "
    11 "
    12 
    12 
       
    13 'From Smalltalk/X, Version:3.5.3 on 27-jul-1999 at 07:46:55'                    !
       
    14 
    13 Object subclass:#Exception
    15 Object subclass:#Exception
    14 	instanceVariableNames:'signal parameter errorString suspendedContext handlerContext
    16 	instanceVariableNames:'signal parameter errorString suspendedContext handlerContext
    15 		rejected originator resumeBlock rejectBlock proceedable'
    17 		rejected originator resumeBlock rejectBlock proceedable'
    16 	classVariableNames:'EmergencyHandler RecursiveExceptionSignal'
    18 	classVariableNames:'EmergencyHandler RecursiveExceptionSignal'
    17 	poolDictionaries:''
    19 	poolDictionaries:''
    43 "
    45 "
    44 !
    46 !
    45 
    47 
    46 documentation
    48 documentation
    47 "
    49 "
    48     Exception and its subclasses implement the same protocal as Signal.
    50     Exception and its subclasses implement the same protocol as Signal.
    49     So class based exceptions may be implemented as subclasses of Exception.
    51     So class based exceptions may be implemented as subclasses of Exception.
    50 
    52 
    51     Instances of Exception are passed to a Signal handling block as argument.
    53     Instances of Exception are passed to a Signal handling block as argument.
    52     The handler block may perform various actions by sending corresponding messages
    54     The handler block may perform various actions by sending corresponding messages
    53     to the exception object. The following actions are possible:
    55     to the exception object. The following actions are possible:
    54 
    56 
    55 	reject          - dont handle this signal;
    57         reject          - don't handle this signal;
    56 			  another handler will be searched for, 
    58                           another handler will be searched for, 
    57 			  upper in the calling hierarchy
    59                           upper in the calling hierarchy
    58 
    60 
    59 	proceed         - return from the Signal>>raise, with nil as value
    61         proceed         - return from the Signal>>raise, with nil as value
    60 
    62 
    61 	proceedWith:val - same, but return val from Signal>>raise
    63         proceedWith:val - same, but return val from Signal>>raise
    62 
    64 
    63 	return          - return from the Signal>>handle:do:, with nil as value
    65         return          - return from the Signal>>handle:do:, with nil as value
    64 
    66 
    65 	returnWith:val  - same, but return val from Signal>>handle:do:
    67         returnWith:val  - same, but return val from Signal>>handle:do:
    66 			  (this is also the handlers default, 
    68                           (this is also the handlers default, 
    67 			   if it falls through; taking the handlerBlocks value
    69                            if it falls through; taking the handlerBlocks value
    68 			   as return value)
    70                            as return value)
    69 
    71 
    70 	restart         - restart the Signal>>handle:do:, after repairing
    72         restart         - restart the Signal>>handle:do:, after repairing
    71 
    73 
    72     Via the Exception object, the handler can also query the state of execution:
    74     Via the Exception object, the handler can also query the state of execution:
    73     where the Signal was raised, where the handler is, the signal which caused
    75     where the Signal was raised, where the handler is, the signal which caused
    74     the error and the errorString passed when the signal was raised. Also, an optional
    76     the error and the errorString passed when the signal was raised. Also, an optional
    75     parameter can be passed - the use is signal specific.:
    77     parameter can be passed - the use is signal specific.
    76 
    78 
    77     [instance variables:]
    79     [instance variables:]
    78 	signal           <Signal>     the signal which caused the exception
    80         signal           <Signal>     the signal which caused the exception
    79 
    81 
    80 	parameter        <Object>     a parameter (if any) which was passed when raising
    82         parameter        <Object>     a parameter (if any) which was passed when raising
    81 				      the signal (only if raised with #raiseWith:aParameter)
    83                                       the signal (only if raised with #raiseWith:aParameter)
    82 
    84 
    83 	errorString      <String>     an errorString 
    85         errorString      <String>     an errorString 
    84 				      (usually the signals own errorString, but sometimes
    86                                       (usually the signals own errorString, but sometimes
    85 				       changed explicitely in #raiseWith:errorString:)
    87                                        changed explicitely in #raiseWith:errorString:)
    86 
    88 
    87 	suspendedContext <Context>    the context in which the raise occured
    89         suspendedContext <Context>    the context in which the raise occured
    88 
    90 
    89 	handlerContext   <Context>    the context of the handler (if any)
    91         handlerContext   <Context>    the context of the handler (if any)
    90 
    92 
    91 	resumeBlock      <Block>      private to the exception; needed to perform resume action
    93         resumeBlock      <Block>      private to the exception; needed to perform resume action
    92 
    94 
    93 	rejectBlock      <Block>      private to the exception; needed to perform reject action
    95         rejectBlock      <Block>      private to the exception; needed to perform reject action
    94 
    96 
    95     In case of an unhandled signal raise, Exceptions EmergenyHandler will be evaluated. 
    97     In case of an unhandled signal raise, Exceptions EmergenyHandler will be evaluated. 
    96     The default emergeny handler will enter the debugger.
    98     The default emergeny handler will enter the debugger.
    97 
    99 
    98     For applications, which do not want Debuggers to come up, other handlers are
   100     For applications, which do not want Debuggers to come up, other handlers are
    99     possible.
   101     possible.
   100     For example, to get the typical C++ behavior, use:
   102     For example, to get the typical C++ behavior, use:
   101 	Exception emergencyHandler:[:ex | Smalltalk exitWithCoreDump]
   103         Exception emergencyHandler:[:ex | Smalltalk exitWithCoreDump]
   102 
   104 
   103 
   105 
   104     [Class variables:]
   106     [Class variables:]
   105 	EmergencyHandler <Block>    this block is evaluated, if no handler was defined
   107         EmergencyHandler <Block>    this block is evaluated, if no handler was defined
   106 				    for a signal (i.e. this one is responsible for the
   108                                     for a signal (i.e. this one is responsible for the
   107 				    unhandled exception debugger).
   109                                     unhandled exception debugger).
   108 				    Having this being a block allows to globally catch
   110                                     Having this being a block allows to globally catch
   109 				    these errors - even when no enclosing handler-scope
   111                                     these errors - even when no enclosing handler-scope
   110 				    around the erronous code exists.
   112                                     around the erronous code exists.
   111 				    (as the catch/through does).
   113                                     (as the catch/through does).
   112 
   114 
   113 	RecursiveExceptionSignal
   115         RecursiveExceptionSignal
   114 			 <Signal>   raised when within a handler for some signal,
   116                          <Signal>   raised when within a handler for some signal,
   115 				    the same signal is raised again.
   117                                     the same signal is raised again.
   116 
   118 
   117 
   119 
   118     [see also:]
   120     [see also:]
   119 	Signal  SignalSet QuerySignal
   121         Signal  SignalSet QuerySignal
   120 	Context Block
   122         Context Block
   121 	Object DebugView
   123         Object DebugView
   122 	(``Exception handling and signals'': programming/exceptions.html)
   124         (``Exception handling and signals'': programming/exceptions.html)
   123 
   125 
   124     [author:]
   126     [author:]
   125 	Claus Gittinger
   127         Claus Gittinger
   126 "
   128 "
   127 !
   129 !
   128 
   130 
   129 examples
   131 examples
   130 "
   132 "
   305     "Modified: / 25.3.1997 / 12:12:37 / cg"
   307     "Modified: / 25.3.1997 / 12:12:37 / cg"
   306     "Created: / 23.7.1999 / 14:23:38 / stefan"
   308     "Created: / 23.7.1999 / 14:23:38 / stefan"
   307 !
   309 !
   308 
   310 
   309 handlerBlock
   311 handlerBlock
   310     "Compatibility with Signal. Class based exeption do not have a handler
   312     "Compatibility with Signal. Class based exeptions do not have a handler
   311      block. They redefine the #action method instead"
   313      block. They redefine the #action method instead"
   312 
   314 
   313     ^ nil
   315     ^ nil
   314 
   316 
   315     "Created: / 23.7.1999 / 14:43:18 / stefan"
   317     "Created: / 23.7.1999 / 14:43:18 / stefan"
       
   318     "Modified: / 24.7.1999 / 20:52:10 / stefan"
   316 ! !
   319 ! !
   317 
   320 
   318 !Exception class methodsFor:'compatibility - queries'!
   321 !Exception class methodsFor:'compatibility - queries'!
   319 
   322 
   320 accepts:aSignal
   323 accepts:aSignal
   333     ^ false
   336     ^ false
   334 
   337 
   335     "Created: / 23.7.1999 / 14:00:47 / stefan"
   338     "Created: / 23.7.1999 / 14:00:47 / stefan"
   336 !
   339 !
   337 
   340 
       
   341 handlerForSignal:signal context:theContext originator:originator
       
   342     "answer the handler block for the signal from originator.
       
   343      The block is retrieved from aContext.
       
   344      Answer nil if the signal is not handled"
       
   345 
       
   346 
       
   347     (theContext selector ~~ #'handle:from:do:'
       
   348      or:[(theContext argAt:2) == originator]) ifTrue:[
       
   349         (self accepts:signal) ifTrue:[
       
   350             ^ theContext argAt:1
       
   351         ]
       
   352     ].
       
   353 
       
   354     ^ nil
       
   355 
       
   356     "Created: / 25.7.1999 / 19:52:58 / stefan"
       
   357 !
       
   358 
   338 inheritsFrom:anotherSignal
   359 inheritsFrom:anotherSignal
   339     "return true, if the receiver is a child of anotherSignal
   360     "return true, if the receiver is a child of anotherSignal
   340      (i.e. if handling anotherSignal also handles the receiver)
   361      (i.e. if handling anotherSignal also handles the receiver)
   341      This is almost the same as accepts, but returns false, if
   362      This is almost the same as accepts, but returns false, if
   342      the receiver is identical to anotherSignal."
   363      the receiver is identical to anotherSignal."
   363 
   384 
   364     |con r|
   385     |con r|
   365 
   386 
   366     con := aContext.
   387     con := aContext.
   367     [con notNil] whileTrue:[
   388     [con notNil] whileTrue:[
   368 	con := con findNextContextWithSelector:#'handle:do:' or:#'handle:from:do:' or:nil.
   389         con := con findSpecialHandle:true raise:false.
   369 	con notNil ifTrue:[
   390         con notNil ifTrue:[
   370 	    "
   391             ((r := con receiver) notNil
   371 	     is this is a #handle:do: or a #handle:from:do: context
   392              and:[(r handlerForSignal:self context:con originator:nil) notNil]
   372 	     with self in it ?
   393             ) ifTrue:[
   373 	    "
   394                 "found a handler context"
   374 
   395                 ^ true
   375 	    ((r := con receiver) notNil
   396             ]
   376 	    and:[r accepts:self]) ifTrue:[
   397         ]
   377 		"found a handler context"
       
   378 
       
   379 		^ true
       
   380 	    ]
       
   381 	]
       
   382     ].
   398     ].
   383     ^ false
   399     ^ false
   384 
   400 
   385     "Created: / 23.7.1999 / 14:03:34 / stefan"
   401     "Created: / 23.7.1999 / 14:03:34 / stefan"
       
   402     "Modified: / 25.7.1999 / 22:59:03 / stefan"
   386 !
   403 !
   387 
   404 
   388 isQuerySignal
   405 isQuerySignal
   389     "return true, if this is a querySignal - always return false here"
   406     "return true, if this is a querySignal - always return false here"
   390 
   407 
   428     "Modified: / 23.7.1999 / 16:15:38 / stefan"
   445     "Modified: / 23.7.1999 / 16:15:38 / stefan"
   429 ! !
   446 ! !
   430 
   447 
   431 !Exception class methodsFor:'compatibility - raising'!
   448 !Exception class methodsFor:'compatibility - raising'!
   432 
   449 
       
   450 new
       
   451 
       
   452     ^ self basicNew signal:self.
       
   453 
       
   454     "Modified: / 23.7.1999 / 13:53:12 / stefan"
       
   455     "Created: / 24.7.1999 / 13:21:13 / stefan"
       
   456 !
       
   457 
   433 newException
   458 newException
   434 
   459 
   435     ^ self new signal:self.
   460     ^ self new
   436 
   461 
   437     "Created: / 23.7.1999 / 13:45:49 / stefan"
   462     "Created: / 23.7.1999 / 13:45:49 / stefan"
   438     "Modified: / 23.7.1999 / 13:53:12 / stefan"
   463     "Modified: / 24.7.1999 / 13:21:25 / stefan"
   439 !
   464 !
   440 
   465 
   441 newExceptionFrom:originator
   466 newExceptionFrom:originator
   442     "answer a new exception object for this signal.
   467     "answer a new exception object for this signal.
   443      Set the originator.
   468      Set the originator.
   676      The handler may decide how to react to the signal by sending
   701      The handler may decide how to react to the signal by sending
   677      a corresponding message to the exception (see there).
   702      a corresponding message to the exception (see there).
   678      If the signal is not raised, return the value of evaluating
   703      If the signal is not raised, return the value of evaluating
   679      aBlock."
   704      aBlock."
   680 
   705 
       
   706      thisContext markForHandle.
   681      ^ aBlock value  "the real logic is in Exception>>doRaise"
   707      ^ aBlock value  "the real logic is in Exception>>doRaise"
   682 
   708 
   683       "
   709       "
   684        Object messageNotUnderstoodSignal handle:[:ex |
   710        Object messageNotUnderstoodSignal handle:[:ex |
   685 	  'oops' printNL.
   711           'oops' printNL.
   686 	  ex return
   712           ex return
   687        ] do:[
   713        ] do:[
   688 	  123 size open   
   714           123 size open   
   689        ]
   715        ]
   690       "
   716       "
   691 
   717 
   692       "
   718       "
   693        |num|
   719        |num|
   694 
   720 
   695        num := 0.
   721        num := 0.
   696        Number divisionByZeroSignal handle:[:ex |
   722        Number divisionByZeroSignal handle:[:ex |
   697 	  'oops' printNL.
   723           'oops' printNL.
   698 	  ex return
   724           ex return
   699        ] do:[
   725        ] do:[
   700 	  123 / num   
   726           123 / num   
   701        ]
   727        ]
   702       "
   728       "
   703 
   729 
   704     "Modified: / 2.3.1998 / 14:28:26 / stefan"
       
   705     "Created: / 23.7.1999 / 14:06:13 / stefan"
   730     "Created: / 23.7.1999 / 14:06:13 / stefan"
       
   731     "Modified: / 25.7.1999 / 19:44:05 / stefan"
   706 !
   732 !
   707 
   733 
   708 handle:handleBlock from:anObject do:aBlock
   734 handle:handleBlock from:anObject do:aBlock
   709     "evaluate the argument, aBlock.
   735     "evaluate the argument, aBlock.
   710      If the receiver-signal is raised during evaluation,
   736      If the receiver-signal is raised during evaluation,
   713      The handler may decide how to react to the signal by sending
   739      The handler may decide how to react to the signal by sending
   714      a corresponding message to the exception (see there).
   740      a corresponding message to the exception (see there).
   715      If the signal is not raised, return the value of evaluating
   741      If the signal is not raised, return the value of evaluating
   716      aBlock."
   742      aBlock."
   717 
   743 
       
   744      thisContext markForHandle.
   718      ^ aBlock value  "the real logic is in Exception>>doRaise"
   745      ^ aBlock value  "the real logic is in Exception>>doRaise"
   719 
   746 
   720       "
   747       "
   721        the first open will be caught; the second not:
   748        the first open will be caught; the second not:
   722 
   749 
   723        |o1 o2|
   750        |o1 o2|
   724 
   751 
   725        o1 := 123.
   752        o1 := 123.
   726        o2 := nil.
   753        o2 := nil.
   727        Object messageNotUnderstoodSignal 
   754        Object messageNotUnderstoodSignal 
   728 	   handle:
   755            handle:
   729 		[:ex |
   756                 [:ex |
   730 		    'oops' printNL.
   757                     'oops' printNL.
   731 		    ex proceed
   758                     ex proceed
   732 		] 
   759                 ] 
   733 	   from:o1
   760            from:o1
   734 	   do:
   761            do:
   735 		[
   762                 [
   736 		    o1 open.
   763                     o1 open.
   737 		    o2 open
   764                     o2 open
   738 		]
   765                 ]
   739       "
   766       "
   740 
   767 
   741     "Modified: / 2.3.1998 / 14:28:05 / stefan"
       
   742     "Created: / 23.7.1999 / 14:06:26 / stefan"
   768     "Created: / 23.7.1999 / 14:06:26 / stefan"
       
   769     "Modified: / 25.7.1999 / 19:44:13 / stefan"
   743 !
   770 !
   744 
   771 
   745 ignoreIn:aBlock
   772 ignoreIn:aBlock
   746      "evaluate the argument, aBlock.
   773      "evaluate the argument, aBlock.
   747       Ignore the receiver-signal during evaluation - i.e. simply
   774       Ignore the receiver-signal during evaluation - i.e. simply
  1184 action
  1211 action
  1185     "perform a action for the signal if it hasn't been catched
  1212     "perform a action for the signal if it hasn't been catched
  1186      We arrive here, if either no handler was found, or none of the
  1213      We arrive here, if either no handler was found, or none of the
  1187      handlers did a return (i.e. every handler rejected or fell through).
  1214      handlers did a return (i.e. every handler rejected or fell through).
  1188 
  1215 
  1189      The default is to evaluate the signal's handlerBlock.
  1216      The default is to evaluate the signal's handlerBlock or the
       
  1217      per process handler (if its the noHandlerSignal).
       
  1218      Finally fall back to Exceptions emergencyHandler, which is always
       
  1219      available and enters the debugger.
  1190      Subclasses may redefine this."
  1220      Subclasses may redefine this."
  1191 
  1221 
  1192     |block noHandlerSignal msg|
  1222     |block noHandlerSignal msg|
  1193 
  1223 
  1194     "
  1224     "
  1195      try per signal handler
  1225      try per signal handler
  1196     "
  1226     "
  1197     (block := signal handlerBlock) isNil ifTrue:[
  1227     (block := signal handlerBlock) isNil ifTrue:[
  1198 	"/
  1228         "/
  1199 	"/ if its a querySignal, ignore it
  1229         "/ if its a querySignal, ignore it
  1200 	"/
  1230         "/
  1201 	signal isQuerySignal ifTrue:[^ nil].
  1231         signal isQuerySignal ifTrue:[^ nil].
  1202 
  1232 
  1203 	"/
  1233         "/
  1204 	"/ if it is not the NoHandlerSignal, raise it ...
  1234         "/ if it is not the NoHandlerSignal, raise it ...
  1205 	"/ passing the receiver as parameter.
  1235         "/ passing the receiver as parameter.
  1206 	"/
  1236         "/
  1207 	signal ~~ (noHandlerSignal := Signal noHandlerSignal) ifTrue:[
  1237         signal ~~ (noHandlerSignal := Signal noHandlerSignal) ifTrue:[
  1208 	    noHandlerSignal notNil ifTrue:[
  1238             noHandlerSignal notNil ifTrue:[
  1209 		handlerContext notNil ifTrue:[
  1239                 handlerContext notNil ifTrue:[
  1210 		    msg := 'unhandled (rejected)'
  1240                     msg := 'unhandled (rejected)'
  1211 		] ifFalse:[
  1241                 ] ifFalse:[
  1212 		    msg := 'unhandled'
  1242                     msg := 'unhandled'
  1213 		].
  1243                 ].
  1214 		msg := msg , ' exception: (' , self errorString , ')'.
  1244                 msg := msg , ' exception: (' , self errorString , ')'.
  1215 		^ noHandlerSignal 
  1245                 ^ noHandlerSignal 
  1216 		      raiseRequestWith:self 
  1246                       raiseRequestWith:self 
  1217 			   errorString:msg
  1247                            errorString:msg
  1218 				    in:self suspendedContext
  1248                                     in:self suspendedContext
  1219 	    ].
  1249             ].
  1220 	    "/
  1250             "/
  1221 	    "/ mhmh - an error during early startup; noHandlerSignal is
  1251             "/ mhmh - an error during early startup; noHandlerSignal is
  1222 	    "/ not yet defined.
  1252             "/ not yet defined.
  1223 	    "/
  1253             "/
  1224 	    ^ MiniDebugger enterWithMessage:self errorString
  1254             ^ MiniDebugger enterWithMessage:self errorString
  1225 	].
  1255         ].
  1226 
  1256 
  1227 	"
  1257         "
  1228 	 mhmh - smells like trouble - there is no handler and
  1258          mhmh - smells like trouble - there is no handler and
  1229 	 no per-signal handler block.
  1259          no per-signal handler block.
  1230 	 Look for either a per-process emergencyHandlerBlock 
  1260          Look for either a per-process emergencyHandlerBlock 
  1231 	 or the global emergencyHandler (from Exception) ...
  1261          or the global emergencyHandler (from Exception) ...
  1232 	"
  1262         "
  1233 	Processor notNil ifTrue:[ 
  1263         Processor notNil ifTrue:[ 
  1234 	    "care for signal during startup (Processor not yet created)"
  1264             "care for signal during startup (Processor not yet created)"
  1235 	    block := Processor activeProcess emergencySignalHandler.
  1265             block := Processor activeProcess emergencySignalHandler.
  1236 	].
  1266         ].
  1237 	block isNil ifTrue:[
  1267         block isNil ifTrue:[
  1238 	    block := Exception emergencyHandler.
  1268             block := Exception emergencyHandler.
  1239 	    block isNil ifTrue:[
  1269             block isNil ifTrue:[
  1240 		"care for error during startup (Exception not yet initialized)"
  1270                 "care for error during startup (Exception not yet initialized)"
  1241 		^ MiniDebugger enterWithMessage:self errorString
  1271                 ^ MiniDebugger enterWithMessage:self errorString
  1242 	    ].
  1272             ].
  1243 	].
  1273         ].
  1244     ].
  1274     ].
  1245     "... and call it"
  1275     "... and call it"
  1246     ^ block value:self.
  1276     ^ block value:self.
  1247 
  1277 
  1248     "Created: / 23.7.1999 / 14:38:03 / stefan"
  1278     "Created: / 23.7.1999 / 14:38:03 / stefan"
  1249     "Modified: / 23.7.1999 / 14:41:36 / stefan"
  1279     "Modified: / 25.7.1999 / 20:11:12 / stefan"
  1250 !
  1280 !
  1251 
  1281 
  1252 mayProceed
  1282 mayProceed
  1253     "return true, if the exception handler is allowed to proceed
  1283     "return true, if the exception handler is allowed to proceed
  1254      the execution where the exception occured.
  1284      the execution where the exception occured.
  1408     "Modified: 27.3.1997 / 16:46:51 / cg"
  1438     "Modified: 27.3.1997 / 16:46:51 / cg"
  1409 ! !
  1439 ! !
  1410 
  1440 
  1411 !Exception methodsFor:'private'!
  1441 !Exception methodsFor:'private'!
  1412 
  1442 
  1413 doCallHandler:aHandler
  1443 XXdoRaise
  1414     "call the handler proper - needed an extra method
       
  1415      to have a separate returnContext for the rejectBlock.
       
  1416      (which is historical, and actually no longer needed)"
       
  1417 
       
  1418     |val|
       
  1419 
       
  1420     rejectBlock := [^ self]. "this will return on reject"
       
  1421     val := aHandler value:self.
       
  1422     "
       
  1423      handler fall through - is just like a returnWith:blocks-value
       
  1424     "
       
  1425     rejectBlock := nil.
       
  1426     self returnWith:val
       
  1427 !
       
  1428 
       
  1429 doRaise
       
  1430     "search through the context-calling chain for a 'handle:do:'-context 
  1444     "search through the context-calling chain for a 'handle:do:'-context 
  1431      to the raising signal, a parent of it, or a SignalSet which includes 
  1445      to the raising signal, a parent of it, or a SignalSet which includes 
  1432      the raising signal.
  1446      the raising signal.
  1433      If found, take the contexts 2nd argument (the handler) and evaluate
  1447      If found, take the contexts 2nd argument (the handler) and evaluate
  1434      it with the receiver exception as argument.
  1448      it with the receiver exception as argument.
  1445 
  1459 
  1446     "/ is nil a valid originator? If so, we need an extra
  1460     "/ is nil a valid originator? If so, we need an extra
  1447     "/ instanceVariable to record the originator setting.
  1461     "/ instanceVariable to record the originator setting.
  1448 
  1462 
  1449     originator isNil ifTrue:[
  1463     originator isNil ifTrue:[
  1450 	originator := suspendedContext homeReceiver
  1464         originator := suspendedContext homeReceiver
  1451     ].
  1465     ].
  1452 
  1466 
  1453     theSignal := signal.
  1467     theSignal := signal.
  1454     theSignal isSignal ifFalse:[
  1468     theSignal isSignal ifFalse:[
  1455 	self halt:'unexpected non-Signal in calling context'.
  1469         self halt:'unexpected non-Signal in calling context'.
  1456     ].
  1470     ].
  1457 
  1471 
  1458 "/ 'search handler for: ' print. theSignal displayString printCR.
  1472 "/ 'search handler for: ' print. theSignal displayString printCR.
  1459 
  1473 
  1460     inHandler := false.
  1474     inHandler := false.
  1461     c := thisContext sender sender.    "the raise/raiseRequest-context"
  1475     c := thisContext sender sender.    "the raise/raiseRequest-context"
  1462 				       "the signal raise context"
  1476                                        "the signal raise context"
  1463 
  1477 
  1464     "/ since the exceptionHandler is evaluated onTop of the
  1478     "/ since the exceptionHandler is evaluated onTop of the
  1465     "/ contextChain, we must skip active handlers before searching.
  1479     "/ contextChain, we must skip active handlers before searching.
  1466     "/ otherwise, we get into trouble, when re-raising an exception
  1480     "/ otherwise, we get into trouble, when re-raising an exception
  1467     "/ from within a handler (which would lead to re-executing the
  1481     "/ from within a handler (which would lead to re-executing the
  1473     "/ in most cases ...
  1487     "/ in most cases ...
  1474 
  1488 
  1475     firstHandler := nil.
  1489     firstHandler := nil.
  1476 
  1490 
  1477     [c notNil] whileTrue:[
  1491     [c notNil] whileTrue:[
  1478 	firstHandler isNil ifTrue:[
  1492         firstHandler isNil ifTrue:[
  1479 	    c := c findNextContextWithSelector:#doRaise or:#'handle:do:' or:#'handle:from:do:'.
  1493             c := c findNextContextWithSelector:#doRaise or:#'handle:do:' or:#'handle:from:do:'.
  1480 	] ifFalse:[
  1494         ] ifFalse:[
  1481 	    c := c findNextContextWithSelector:#doRaise or:nil or:nil.
  1495             c := c findNextContextWithSelector:#doRaise or:nil or:nil.
  1482 	].
  1496         ].
  1483 	c notNil ifTrue:[
  1497         c notNil ifTrue:[
  1484 	    (c selector == #doRaise) ifTrue:[
  1498             (c selector == #doRaise) ifTrue:[
  1485 
  1499 
  1486 		ex1 := c receiver.
  1500                 ex1 := c receiver.
  1487 
  1501 
  1488 		((ex1 class == self class)
  1502                 ((ex1 class == self class)
  1489 		or:[ex1 species == self species]) ifTrue:[
  1503                 or:[ex1 species == self species]) ifTrue:[
  1490 		    (ex1 signal == theSignal) ifTrue:[
  1504                     (ex1 signal == theSignal) ifTrue:[
  1491 			h := ex1 handlerContext.
  1505                         h := ex1 handlerContext.
  1492 			h notNil ifTrue:[
  1506                         h notNil ifTrue:[
  1493 			    r := h receiver.
  1507                             r := h receiver.
  1494 			    (r notNil and:[r accepts:theSignal]) ifTrue:[
  1508                             (r notNil and:[r accepts:theSignal]) ifTrue:[
  1495 				activeHandlers isNil ifTrue:[
  1509                                 activeHandlers isNil ifTrue:[
  1496 				    activeHandlers := OrderedCollection new
  1510                                     activeHandlers := OrderedCollection new
  1497 				].
  1511                                 ].
  1498 
  1512 
  1499 				lastHandler := h.
  1513                                 lastHandler := h.
  1500 				activeHandlers add:lastHandler.
  1514                                 activeHandlers add:lastHandler.
  1501 				inHandler := true.
  1515                                 inHandler := true.
  1502 				c := lastHandler.
  1516                                 c := lastHandler.
  1503 			    ]
  1517                             ]
  1504 			]
  1518                         ]
  1505 		    ]
  1519                     ]
  1506 		]
  1520                 ]
  1507 	    ] ifFalse:[
  1521             ] ifFalse:[
  1508 		"/ must be a #handle:do context ...
  1522                 "/ must be a #handle:do context ...
  1509 		firstHandler := c.
  1523                 firstHandler := c.
  1510 	    ]
  1524             ]
  1511 	]
  1525         ]
  1512     ].
  1526     ].
  1513 
  1527 
  1514     "/ now, start searching for a handler,
  1528     "/ now, start searching for a handler,
  1515     "/ start search above the last active handler.
  1529     "/ start search above the last active handler.
  1516     "/ Or start with the first handle:do: context, if one
  1530     "/ Or start with the first handle:do: context, if one
  1520 
  1534 
  1521 "/    lastHandler notNil ifTrue:[
  1535 "/    lastHandler notNil ifTrue:[
  1522 "/        theContext := lastHandler.
  1536 "/        theContext := lastHandler.
  1523 "/        theContext := lastHandler findNextContextWithSelector:#'handle:do:' or:#'handle:from:do:' or:nil.
  1537 "/        theContext := lastHandler findNextContextWithSelector:#'handle:do:' or:#'handle:from:do:' or:nil.
  1524 "/    ] ifFalse:[
  1538 "/    ] ifFalse:[
  1525 	theContext := firstHandler.
  1539         theContext := firstHandler.
  1526 "/    ].
  1540 "/    ].
  1527 
  1541 
  1528     [theContext notNil] whileTrue:[
  1542     [theContext notNil] whileTrue:[
  1529 	(theContext selector == #'handle:do:'
  1543         (theContext selector == #'handle:do:'
  1530 	or:[(theContext argAt:2) == originator]) 
  1544         or:[(theContext argAt:2) == originator]) 
  1531 	ifTrue:[
  1545         ifTrue:[
  1532 	    (activeHandlers notNil
  1546             (activeHandlers notNil
  1533 	     and:[activeHandlers includesIdentical:theContext]) ifTrue:[
  1547              and:[activeHandlers includesIdentical:theContext]) ifTrue:[
  1534 "/                'skip activeHandler: ' print. theContext displayString printCR.
  1548 "/                'skip activeHandler: ' print. theContext displayString printCR.
  1535 
  1549 
  1536 	    ] ifFalse:[
  1550             ] ifFalse:[
  1537 		"
  1551                 "
  1538 		 if this is the Signal>>handle:do: context
  1552                  if this is the Signal>>handle:do: context
  1539 		 or a SignalSet>>handle:do: context with self in it,
  1553                  or a SignalSet>>handle:do: context with self in it,
  1540 		 call the handler
  1554                  call the handler
  1541 		"
  1555                 "
  1542 		r := theContext receiver.
  1556                 r := theContext receiver.
  1543 		(r notNil and:[r accepts:signal]) ifTrue:[
  1557                 (r notNil and:[r accepts:signal]) ifTrue:[
  1544 		    "call the handler"
  1558                     "call the handler"
  1545 
  1559 
  1546 		    conArg1 := theContext argAt:1.
  1560                     conArg1 := theContext argAt:1.
  1547 
  1561 
  1548 		    handlerContext := theContext.
  1562                     handlerContext := theContext.
  1549 
  1563 
  1550 		    self doCallHandler:conArg1.
  1564                     self doCallHandler:conArg1.
  1551 
  1565 
  1552 		    "/ if the handler rejects, we arrive here
  1566                     "/ if the handler rejects, we arrive here
  1553 		    "/ continue search for another handler
  1567                     "/ continue search for another handler
  1554 		].
  1568                 ].
  1555 	    ]
  1569             ]
  1556 	].
  1570         ].
  1557 	theContext := theContext findNextContextWithSelector:#'handle:do:' or:#'handle:from:do:' or:nil.
  1571         theContext := theContext findNextContextWithSelector:#'handle:do:' or:#'handle:from:do:' or:nil.
  1558     ].
  1572     ].
  1559 
  1573 
  1560     activeHandlers := nil.
  1574     activeHandlers := nil.
  1561 
  1575 
  1562     "
  1576     "
  1564      handlers did a return (i.e. every handler rejected or fell through).
  1578      handlers did a return (i.e. every handler rejected or fell through).
  1565     "
  1579     "
  1566 
  1580 
  1567     ^ self action
  1581     ^ self action
  1568 
  1582 
       
  1583     "Modified: / 9.11.1997 / 14:48:44 / cg"
       
  1584     "Modified: / 23.7.1999 / 14:40:12 / stefan"
       
  1585     "Created: / 25.7.1999 / 20:13:19 / stefan"
       
  1586 !
       
  1587 
       
  1588 doCallHandler:aHandler
       
  1589     "call the handler proper - needed an extra method
       
  1590      to have a separate returnContext for the rejectBlock.
       
  1591      (which is historical, and actually no longer needed)"
       
  1592 
       
  1593     |val|
       
  1594 
       
  1595     rejectBlock := [^ self]. "this will return on reject"
       
  1596 
       
  1597     thisContext markForRaise.
       
  1598 
       
  1599     val := aHandler value:self.
       
  1600     "
       
  1601      handler fall through - is just like a returnWith:blocks-value
       
  1602     "
       
  1603     rejectBlock := nil.
       
  1604     self returnWith:val
       
  1605 
       
  1606     "Modified: / 26.7.1999 / 14:41:55 / stefan"
       
  1607 !
       
  1608 
       
  1609 doRaise
       
  1610     "search through the context-calling chain for a handle-context 
       
  1611      to the raising signal, a parent of it, or a SignalSet which includes 
       
  1612      the raising signal.
       
  1613      If found, ask the receiver for the handler and evaluate
       
  1614      it with the receiver exception as argument.
       
  1615      If no handler is found, perform the default #action method.
       
  1616 
       
  1617      ATTENTION: the code below depends on being called by #raise or
       
  1618      #raiseRequest for proper operation (it skips the sending context)."
       
  1619 
       
  1620     |theContext handler
       
  1621      theSignal c ex1 activeHandlers inHandler 
       
  1622      lastHandler h r firstHandler|
       
  1623 
       
  1624 
       
  1625     "/ is nil a valid originator? If so, we need an extra
       
  1626     "/ instanceVariable to record the originator setting.
       
  1627 
       
  1628     originator isNil ifTrue:[
       
  1629         originator := suspendedContext homeReceiver
       
  1630     ].
       
  1631 
       
  1632     theSignal := signal.
       
  1633     theSignal isSignal ifFalse:[
       
  1634         self halt:'unexpected non-Signal in calling context'.
       
  1635     ].
       
  1636 
       
  1637 "/ 'search handler for: ' print. theSignal displayString printCR.
       
  1638 
       
  1639     inHandler := false.
       
  1640     c := thisContext sender sender.    "the raise/raiseRequest-context"
       
  1641                                        "the signal raise context"
       
  1642 
       
  1643     "/ since the exceptionHandler is evaluated on top of the
       
  1644     "/ contextChain, we must skip active handlers before searching.
       
  1645     "/ otherwise, we get into trouble, when re-raising an exception
       
  1646     "/ from within a handler (which would lead to re-executing the
       
  1647     "/ same handler)
       
  1648     "/ the code below collects active handlers ...
       
  1649 
       
  1650     "/ on the fly, look for the first handle - context,
       
  1651     "/ and remember it (as firstHandler) to avoid walking the context chain twice
       
  1652     "/ in most cases ...
       
  1653 
       
  1654     firstHandler := nil.
       
  1655 
       
  1656     [c notNil] whileTrue:[
       
  1657         firstHandler isNil ifTrue:[
       
  1658             c := c findSpecialHandle:true raise:true.
       
  1659         ] ifFalse:[
       
  1660             c := c findSpecialHandle:false raise:true.
       
  1661         ].
       
  1662         c notNil ifTrue:[
       
  1663             (c isRaiseContext) ifTrue:[
       
  1664                 ex1 := c receiver.
       
  1665                 ((ex1 class == self class)
       
  1666                 or:[ex1 species == self species]) ifTrue:[
       
  1667                     (ex1 signal == theSignal) ifTrue:[
       
  1668                         h := ex1 handlerContext.
       
  1669                         h notNil ifTrue:[
       
  1670                             activeHandlers isNil ifTrue:[
       
  1671                                 activeHandlers := OrderedCollection new
       
  1672                             ].
       
  1673 
       
  1674                             lastHandler := h.
       
  1675                             activeHandlers add:lastHandler.
       
  1676                             inHandler := true.
       
  1677                             c := lastHandler.
       
  1678                         ]
       
  1679                     ]
       
  1680                 ]
       
  1681             ] ifFalse:[
       
  1682                 "/ must be a handle context ...
       
  1683                 firstHandler := c.
       
  1684             ]
       
  1685         ]
       
  1686     ].
       
  1687 
       
  1688     "/ now, start searching for a handler,
       
  1689     "/ start search above the last active handler.
       
  1690     "/ Or start with the first handle context, if one
       
  1691     "/ was found as a side effect of the previous handler search.
       
  1692     "/ If nil, then there is no handler and we can directly proceed
       
  1693     "/ to the unhandled code below.
       
  1694 
       
  1695 "/    lastHandler notNil ifTrue:[
       
  1696 "/        theContext := lastHandler.
       
  1697 "/        theContext := lastHandler findNextHandleContext
       
  1698 "/    ] ifFalse:[
       
  1699         theContext := firstHandler.
       
  1700 "/    ].
       
  1701 
       
  1702     [theContext notNil] whileTrue:[
       
  1703         "
       
  1704           ask the Signal instance/Exception class for the handler.
       
  1705           nil is returned, if the signal is not accepted
       
  1706         "
       
  1707 
       
  1708         r := theContext receiver.
       
  1709         (r notNil and:[(handler := r handlerForSignal:signal 
       
  1710                                      context:theContext 
       
  1711                                      originator:originator) notNil]
       
  1712         ) ifTrue:[
       
  1713             (activeHandlers notNil
       
  1714              and:[activeHandlers includesIdentical:theContext]) ifTrue:[
       
  1715 "/                'skip activeHandler: ' print. theContext displayString printCR.
       
  1716 
       
  1717             ] ifFalse:[
       
  1718                 "call the handler"
       
  1719 
       
  1720                 handlerContext := theContext.
       
  1721                 self doCallHandler:handler.
       
  1722 
       
  1723                 "/ if the handler rejects, we arrive here
       
  1724                 "/ continue search for another handler
       
  1725             ].
       
  1726         ].
       
  1727         theContext := theContext findSpecialHandle:true raise:false.
       
  1728     ].
       
  1729 
       
  1730     activeHandlers := nil.
       
  1731 
       
  1732     "
       
  1733      we arrive here, if either no handler was found, or none of the
       
  1734      handlers did a return (i.e. every handler rejected or fell through).
       
  1735     "
       
  1736 
       
  1737     ^ self action
       
  1738 
  1569     "Created: / 12.5.1996 / 15:09:39 / cg"
  1739     "Created: / 12.5.1996 / 15:09:39 / cg"
  1570     "Modified: / 9.11.1997 / 14:48:44 / cg"
  1740     "Modified: / 9.11.1997 / 14:48:44 / cg"
  1571     "Modified: / 23.7.1999 / 14:40:12 / stefan"
  1741     "Modified: / 26.7.1999 / 14:50:50 / stefan"
  1572 ! !
  1742 ! !
  1573 
  1743 
  1574 !Exception methodsFor:'raising'!
  1744 !Exception methodsFor:'raising'!
  1575 
  1745 
  1576 raise
  1746 raise
  1649 ! !
  1819 ! !
  1650 
  1820 
  1651 !Exception class methodsFor:'documentation'!
  1821 !Exception class methodsFor:'documentation'!
  1652 
  1822 
  1653 version
  1823 version
  1654     ^ '$Header: /cvs/stx/stx/libbasic/Exception.st,v 1.70 1999-07-24 10:53:55 stefan Exp $'
  1824     ^ '$Header: /cvs/stx/stx/libbasic/Exception.st,v 1.71 1999-07-28 07:53:24 stefan Exp $'
  1655 ! !
  1825 ! !
  1656 Exception initialize!
  1826 Exception initialize!