Signal.st
changeset 159 514c749165c3
parent 145 217dc62c4ddd
child 171 129f0e2e23df
equal deleted inserted replaced
158:be947d4e7fb2 159:514c749165c3
     1 "
     1 "
     2  COPYRIGHT (c) 1993 by Claus Gittinger
     2  COPYRIGHT (c) 1993 by Claus Gittinger
     3               All Rights Reserved
     3 	      All Rights Reserved
     4 
     4 
     5  This software is furnished under a license and may be used
     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
     6  only in accordance with the terms of that license and with the
     7  inclusion of the above copyright notice.   This software may not
     7  inclusion of the above copyright notice.   This software may not
     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 Object subclass:#Signal
    13 Object subclass:#Signal
    14          instanceVariableNames:'mayProceed notifierString nameClass message
    14 	 instanceVariableNames:'mayProceed notifierString nameClass message
    15                                 handlerBlock'
    15 				handlerBlock parent'
    16          classVariableNames:'NoHandlerSignal'
    16 	 classVariableNames:'NoHandlerSignal RecursiveRaiseSignal'
    17          poolDictionaries:''
    17 	 poolDictionaries:''
    18          category:'Kernel-Exceptions'
    18 	 category:'Kernel-Exceptions'
    19 !
    19 !
    20 
    20 
    21 Signal comment:'
    21 Signal comment:'
    22 COPYRIGHT (c) 1993 by Claus Gittinger
    22 COPYRIGHT (c) 1993 by Claus Gittinger
    23               All Rights Reserved
    23 	      All Rights Reserved
    24 
    24 
    25 $Header: /cvs/stx/stx/libbasic/Signal.st,v 1.13 1994-08-23 23:11:14 claus Exp $
    25 $Header: /cvs/stx/stx/libbasic/Signal.st,v 1.14 1994-10-10 00:28:19 claus Exp $
    26 '!
    26 '!
    27 
    27 
    28 !Signal class methodsFor:'documentation'!
    28 !Signal class methodsFor:'documentation'!
    29 
    29 
    30 copyright
    30 copyright
    31 "
    31 "
    32  COPYRIGHT (c) 1993 by Claus Gittinger
    32  COPYRIGHT (c) 1993 by Claus Gittinger
    33               All Rights Reserved
    33 	      All Rights Reserved
    34 
    34 
    35  This software is furnished under a license and may be used
    35  This software is furnished under a license and may be used
    36  only in accordance with the terms of that license and with the
    36  only in accordance with the terms of that license and with the
    37  inclusion of the above copyright notice.   This software may not
    37  inclusion of the above copyright notice.   This software may not
    38  be provided or otherwise made available to, or used by, any
    38  be provided or otherwise made available to, or used by, any
    41 "
    41 "
    42 !
    42 !
    43 
    43 
    44 version
    44 version
    45 "
    45 "
    46 $Header: /cvs/stx/stx/libbasic/Signal.st,v 1.13 1994-08-23 23:11:14 claus Exp $
    46 $Header: /cvs/stx/stx/libbasic/Signal.st,v 1.14 1994-10-10 00:28:19 claus Exp $
    47 "
    47 "
    48 !
    48 !
    49 
    49 
    50 documentation
    50 documentation
    51 "
    51 "
    96 
    96 
    97     See samples in doc/coding.
    97     See samples in doc/coding.
    98 
    98 
    99     Instance variables:
    99     Instance variables:
   100 
   100 
   101         mayProceed      <Boolean>       hint for the debugger - program may 
   101 	mayProceed      <Boolean>       hint for the debugger - program may 
   102                                         proceed (currently not honored by the
   102 					proceed (currently not honored by the
   103                                         debugger)
   103 					debugger)
   104 
   104 
   105         notifierString  <String>        eror message to be output 
   105 	notifierString  <String>        eror message to be output 
   106 
   106 
   107         nameClass       <???>           I dont know what this is for 
   107 	nameClass       <???>           I dont know what this is for 
   108                                         (included for ST-80 compatibility)
   108 					(included for ST-80 compatibility)
   109 
   109 
   110         message         <???>           I dont know what this is for
   110 	message         <???>           I dont know what this is for
   111                                         (included for ST-80 compatibility)
   111 					(included for ST-80 compatibility)
   112 
   112 
   113         handlerBlock    <Block>         if nonNil, a 1-arg block to be 
   113 	handlerBlock    <Block>         if nonNil, a 1-arg block to be 
   114                                         evaluated when no handler context is 
   114 					evaluated when no handler context is 
   115                                         found. The block gets the exception
   115 					found. The block gets the exception
   116                                         object as argument.
   116 					object as argument.
   117 
   117 
   118     Notice:
   118     Notice:
   119     Part of the implementation is a left-over from old times when the 
   119     Part of the implementation is a left-over from old times when the 
   120     resume/restart things in context did not work properly. Now, with the 
   120     resume/restart things in context did not work properly. Now, with the 
   121     handler- and suspendedContext at hand, the exception can do it using 
   121     handler- and suspendedContext at hand, the exception can do it using 
   123 "
   123 "
   124 ! !
   124 ! !
   125 
   125 
   126 !Signal class methodsFor:'initialization'!
   126 !Signal class methodsFor:'initialization'!
   127 
   127 
   128 initialize
   128 initialize 
   129     "setup the signal used to handle unhandled signals"
   129     "setup the signal used to handle unhandled signals"
   130 
   130 
   131     NoHandlerSignal isNil ifTrue:[
   131     NoHandlerSignal isNil ifTrue:[
   132         NoHandlerSignal := (Signal new) mayProceed:true.
   132 	Object initialize.
   133         NoHandlerSignal notifierString:'unhandled exception'
   133 
       
   134 	NoHandlerSignal := Object errorSignal newSignalMayProceed:true.
       
   135 	NoHandlerSignal nameClass:self message:#noHandlerSignal.
       
   136 	NoHandlerSignal notifierString:'unhandled exception'.
       
   137 
       
   138 	RecursiveRaiseSignal := Object errorSignal newSignalMayProceed:false.
       
   139 	RecursiveRaiseSignal nameClass:self message:#recursiveRaiseSignal.
       
   140 	RecursiveRaiseSignal notifierString:'recursive signal raise'
   134     ]
   141     ]
   135 ! !
   142 ! !
   136 
   143 
   137 !Signal class methodsFor:'instance creation'!
   144 !Signal class methodsFor:'instance creation'!
   138 
   145 
   146 
   153 
   147 noHandlerSignal
   154 noHandlerSignal
   148     "return the signal used to handle unhandled signals"
   155     "return the signal used to handle unhandled signals"
   149 
   156 
   150     ^ NoHandlerSignal
   157     ^ NoHandlerSignal
       
   158 !
       
   159 
       
   160 recursiveRaiseSignal
       
   161     "return the signal used to handle recursive signal raises"
       
   162 
       
   163     ^ RecursiveRaiseSignal
   151 ! !
   164 ! !
   152 
   165 
   153 !Signal methodsFor:'instance creation'!
   166 !Signal methodsFor:'instance creation'!
   154 
   167 
   155 newSignalMayProceed:aBoolean
   168 newSignalMayProceed:aBoolean
   156     "create a new signal, using the receiver as a prototype"
   169     "create a new signal, using the receiver as a prototype and
   157 
   170      setting the parent of the new signal to the receiver."
   158     ^ (self copy) mayProceed:aBoolean
   171 
       
   172     |newSignal|
       
   173 
       
   174     newSignal := (self copy) mayProceed:aBoolean.
       
   175     newSignal parent:self.
       
   176     ^ newSignal
   159 !
   177 !
   160 
   178 
   161 newSignal
   179 newSignal
   162     "create a new signal, using the receiver as a prototype"
   180     "create a new signal, using the receiver as a prototype and
   163 
   181      setting the parent of the new signal to the receiver."
   164     ^ (self copy)
   182 
       
   183     ^ (self copy) parent:self
       
   184 ! !
       
   185 
       
   186 !Signal methodsFor:'copying'!
       
   187 
       
   188 deepCopy
       
   189     "raise an error - deepCopy is not allowed for signals"
       
   190 
       
   191     ^ self deepCopyError
   165 ! !
   192 ! !
   166 
   193 
   167 !Signal methodsFor:'accessing'!
   194 !Signal methodsFor:'accessing'!
   168 
   195 
   169 nameClass:aClass message:aSelector
   196 nameClass:aClass message:aSelector
   170     "I dont know what that is used for (yet)"
   197     "this sets the class & selector of a method which returns
       
   198      that signal - this is simply for documentation purposes -
       
   199      see Signal>>printOn: implementation.
       
   200      (took me a while to find that one out ;-)"
   171 
   201 
   172     nameClass := aClass.
   202     nameClass := aClass.
   173     message := aSelector
   203     message := aSelector
   174 !
   204 !
   175 
   205 
   179      the debugger."
   209      the debugger."
   180 
   210 
   181     mayProceed := aBoolean
   211     mayProceed := aBoolean
   182 !
   212 !
   183 
   213 
       
   214 parent:aSignal 
       
   215     "set the parent-signal of the receiver."
       
   216 
       
   217     parent := aSignal
       
   218 !
       
   219 
       
   220 parent
       
   221     "return the parent-signal of the receiver"
       
   222 
       
   223     ^ parent
       
   224 !
       
   225 
   184 notifierString:aString
   226 notifierString:aString
   185     "set the notifier string"
   227     "set the notifier string"
   186 
   228 
   187     notifierString := aString
   229     notifierString := aString
   188 !
   230 !
   196 handlerBlock:aOneArgBlock
   238 handlerBlock:aOneArgBlock
   197     "set the handlerblock - this will be evaluated with the exception 
   239     "set the handlerblock - this will be evaluated with the exception 
   198      object as argument, if no #handle:do: context was found on the stack."
   240      object as argument, if no #handle:do: context was found on the stack."
   199 
   241 
   200     handlerBlock := aOneArgBlock
   242     handlerBlock := aOneArgBlock
       
   243 ! !
       
   244 
       
   245 !Signal methodsFor:'printing'!
       
   246 
       
   247 printOn:aStream
       
   248     "append a printed representation of the receiver on aStream"
       
   249 
       
   250     nameClass notNil ifTrue:[
       
   251 	aStream nextPutAll:nameClass name.
       
   252 	aStream space.
       
   253 	aStream nextPutAll:message.
       
   254 	^ self
       
   255     ].
       
   256     ^ super printOn:aStream
   201 ! !
   257 ! !
   202 
   258 
   203 !Signal methodsFor:'save evaluation'!
   259 !Signal methodsFor:'save evaluation'!
   204 
   260 
   205 handle:handleBlock do:aBlock
   261 handle:handleBlock do:aBlock
   213 
   269 
   214      ^ aBlock value  "the real logic is in raise/Exception"
   270      ^ aBlock value  "the real logic is in raise/Exception"
   215 
   271 
   216       "
   272       "
   217        Object messageNotUnderstoodSignal handle:[:ex |
   273        Object messageNotUnderstoodSignal handle:[:ex |
   218           'oops' printNL.
   274 	  'oops' printNL.
   219           ex return
   275 	  ex return
   220        ] do:[
   276        ] do:[
   221           123 size open   
   277 	  123 size open   
   222        ]
   278        ]
   223       "
   279       "
   224 
   280 
   225       "
   281       "
   226        |num|
   282        |num|
   227 
   283 
   228        num := 0.
   284        num := 0.
   229        Number divisionByZeroSignal handle:[:ex |
   285        Number divisionByZeroSignal handle:[:ex |
   230           'oops' printNL.
   286 	  'oops' printNL.
   231           ex return
   287 	  ex return
   232        ] do:[
   288        ] do:[
   233           123 / num   
   289 	  123 / num   
   234        ]
   290        ]
   235       "
   291       "
   236 !
   292 !
   237 
   293 
   238 catch:aBlock
   294 catch:aBlock
   239      "evaluate the argument, aBlock; return false.
   295      "evaluate the argument, aBlock.
   240       If the receiver-signal is raised during evaluation, abort
   296       If the receiver-signal is raised during evaluation, abort
   241       the evaluation and return true. 
   297       the evaluation and return true; otherwise return false. 
   242       This is the catch & throw mechanism found in other languages,
   298       This is the catch & throw mechanism found in other languages,
   243       where the returned value indicates if an exception occured."
   299       where the returned value indicates if an exception occured."
   244 
   300 
   245       |raiseOccurred|
   301       |raiseOccurred|
   246 
   302 
   248       self handle:[:ex | raiseOccurred := true. ex return] do:aBlock.
   304       self handle:[:ex | raiseOccurred := true. ex return] do:aBlock.
   249       ^ raiseOccurred
   305       ^ raiseOccurred
   250 
   306 
   251       "
   307       "
   252        Object messageNotUnderstoodSignal catch:[
   308        Object messageNotUnderstoodSignal catch:[
   253           123 size open   
   309 	  123 size open   
   254        ]
   310        ]
   255       "
   311       "
       
   312 !
       
   313 
       
   314 ignore:aBlock
       
   315      "evaluate the argument, aBlock.
       
   316       Ignore the receiver-signal during evaluation - i.e. simply
       
   317       continue. This makes only sense for some signals, such as UserInterrupt
       
   318       or AbortSignals, because continuing after an exception without any cleanup
       
   319       will often lead to followup-errors."
       
   320 
       
   321       ^ self handle:[:ex | ex proceed] do:aBlock.
       
   322 
       
   323       "
       
   324        Object messageNotUnderstoodSignal ignore:[
       
   325 	  123 size open   
       
   326        ]
       
   327       "
   256 ! !
   328 ! !
   257 
   329 
   258 !Signal methodsFor:'queries'!
   330 !Signal methodsFor:'queries'!
       
   331 
       
   332 accepts:aSignal
       
   333     "return true, if the receiver accepts the argument, aSignal.
       
   334      (i.e. the recevier is aSignal or a parent of it). False otherwise."
       
   335 
       
   336     |s|
       
   337 
       
   338     s := aSignal.
       
   339     [s notNil] whileTrue:[
       
   340 	self == s ifTrue:[^ true].
       
   341 	s := s parent
       
   342     ].
       
   343     ^ false
       
   344 !
   259 
   345 
   260 isHandled
   346 isHandled
   261     "return true, if there is a handler for the receiver signal.
   347     "return true, if there is a handler for the receiver signal.
   262      Raising an unhandled signal will usually lead into the debugger,
   348      Raising an unhandled signal will usually lead into the debugger,
   263      but can be cought globally by setting Exceptions EmergencyHandler."
   349      but can be cought globally by setting Exceptions EmergencyHandler."
   265     |con|
   351     |con|
   266 
   352 
   267     con := thisContext.
   353     con := thisContext.
   268     con := con sender.
   354     con := con sender.
   269     [con notNil] whileTrue:[
   355     [con notNil] whileTrue:[
   270         (con selector == #handle:do:) ifTrue:[
   356 	(con selector == #handle:do:) ifTrue:[
   271             "
   357 	    "
   272              is this is the Signal>>handle:do: context
   358 	     is this is the Signal>>handle:do: context
   273              or a SignalSet>>handle:do: context with self in it ?
   359 	     or a SignalSet>>handle:do: context with self in it ?
   274             "
   360 	    "
   275             ((con receiver == self) 
   361 	    (con receiver accepts:self) ifTrue:[
   276             or:[(con receiver isMemberOf:SignalSet) and:[con receiver includes:self]]) ifTrue:[
   362 		"found a handler context"
   277                 "found it"
   363 
   278 
   364 		^ true
   279                 ^ true
   365 	    ].
   280             ].
   366 	].
   281         ].
   367 	con := con sender
   282         con := con sender
       
   283     ].
   368     ].
   284     ^ false
   369     ^ false
   285 ! !
   370 ! !
   286 
   371 
   287 !Signal methodsFor:'raising'!
   372 !Signal methodsFor:'raising'!
   296      (thus making things cleaner in the debugger-walkback eventually)"
   381      (thus making things cleaner in the debugger-walkback eventually)"
   297 
   382 
   298     |ex block|
   383     |ex block|
   299 
   384 
   300     ex := Exception new 
   385     ex := Exception new 
   301               signal:self
   386 	      signal:self
   302               parameter:nil 
   387 	      parameter:nil 
   303               errorString:notifierString
   388 	      errorString:notifierString
   304               suspendedContext:thisContext sender.
   389 	      suspendedContext:thisContext sender.
   305 
   390 
   306     ex resumeBlock:[:value | ^ value].
   391     ex resumeBlock:[:value | ^ value].
   307     self evaluateHandlerWith:ex.
   392     self evaluateHandlerWith:ex.
   308 
   393 
   309     (block := handlerBlock) isNil ifTrue:[
   394     (block := handlerBlock) isNil ifTrue:[
   310         "
   395 	"
   311          if I am not the NoHandlerSignal, raise it ...
   396 	 if I am not the NoHandlerSignal, raise it ...
   312          passing the exception as parameter.
   397 	 passing the exception as parameter.
   313         "
   398 	"
   314         self == NoHandlerSignal ifFalse:[
   399 	self == NoHandlerSignal ifFalse:[
   315             ^ NoHandlerSignal 
   400 	    ^ NoHandlerSignal 
   316                   raiseRequestWith:ex
   401 		  raiseRequestWith:ex
   317                        errorString:('unhandled exception: ' , ex errorString)
   402 		       errorString:('unhandled exception: ' , ex errorString)
   318         ].
   403 	].
   319 
   404 
   320         "
   405 	"
   321          otherwise,
   406 	 otherwise,
   322          take either a per-process emergencyHandlerBlock 
   407 	 take either a per-process emergencyHandlerBlock 
   323          or the global emergencyHandler (from Exception) ...
   408 	 or the global emergencyHandler (from Exception) ...
   324         "
   409 	"
   325         block := Processor activeProcess emergencySignalHandler.
   410 	Processor notNil ifTrue:[ 
   326         block isNil ifTrue:[
   411 	    "care for signal during startup (Processor not yet created)"
   327             block := Exception emergencyHandler
   412 	    block := Processor activeProcess emergencySignalHandler.
   328         ]
   413 	].
       
   414 	block isNil ifTrue:[
       
   415 	    block := Exception emergencyHandler
       
   416 	].
       
   417 	block isNil ifTrue:[
       
   418 	    "care for error during startup (Exception not yet initialized)"
       
   419 	    ^ MiniDebugger enterWithMessage:ex errorString
       
   420 	]
   329     ].
   421     ].
   330 
   422 
   331     "... and call it"
   423     "... and call it"
   332     ^ block value:ex.
   424     ^ block value:ex.
   333 !
   425 !
   342      (thus making things cleaner in the debugger-walkback eventually)"
   434      (thus making things cleaner in the debugger-walkback eventually)"
   343 
   435 
   344     |ex block|
   436     |ex block|
   345 
   437 
   346     ex := Exception new 
   438     ex := Exception new 
   347               signal:self
   439 	      signal:self
   348               parameter:aParameter 
   440 	      parameter:aParameter 
   349               errorString:notifierString
   441 	      errorString:notifierString
   350               suspendedContext:thisContext sender.
   442 	      suspendedContext:thisContext sender.
   351 
   443 
   352     ex resumeBlock:[:value | ^ value].
   444     ex resumeBlock:[:value | ^ value].
   353     self evaluateHandlerWith:ex.
   445     self evaluateHandlerWith:ex.
   354 
   446 
   355     (block := handlerBlock) isNil ifTrue:[
   447     (block := handlerBlock) isNil ifTrue:[
   356         "
   448 	"
   357          if I am not the NoHandlerSignal, raise it ...
   449 	 if I am not the NoHandlerSignal, raise it ...
   358          passing the exception as parameter.
   450 	 passing the exception as parameter.
   359         "
   451 	"
   360         self == NoHandlerSignal ifFalse:[
   452 	self == NoHandlerSignal ifFalse:[
   361             ^ NoHandlerSignal 
   453 	    ^ NoHandlerSignal 
   362                   raiseRequestWith:ex
   454 		  raiseRequestWith:ex
   363                        errorString:('unhandled exception: ' , ex errorString)
   455 		       errorString:('unhandled exception: ' , ex errorString)
   364         ].
   456 	].
   365 
   457 
   366         "
   458 	"
   367          otherwise,
   459 	 otherwise,
   368          take either a per-process emergencyHandlerBlock 
   460 	 take either a per-process emergencyHandlerBlock 
   369          or the global emergencyHandler (from Exception) ...
   461 	 or the global emergencyHandler (from Exception) ...
   370         "
   462 	"
   371         block := Processor activeProcess emergencySignalHandler.
   463 	Processor notNil ifTrue:[ 
   372         block isNil ifTrue:[
   464 	    "care for signal during startup (Processor not yet created)"
   373             block := Exception emergencyHandler
   465 	    block := Processor activeProcess emergencySignalHandler.
   374         ]
   466 	].
       
   467 	block isNil ifTrue:[
       
   468 	    block := Exception emergencyHandler
       
   469 	].
       
   470 	block isNil ifTrue:[
       
   471 	    "care for error during startup (Exception not yet initialized)"
       
   472 	    ^ MiniDebugger enterWithMessage:ex errorString
       
   473 	]
   375     ].
   474     ].
   376 
   475 
   377     "... and call it"
   476     "... and call it"
   378     ^ block value:ex.
   477     ^ block value:ex.
   379 !
   478 !
   385      XXX: I am not certain, if this is the correct behavior (seen in remoteInvocation-goodie)"
   484      XXX: I am not certain, if this is the correct behavior (seen in remoteInvocation-goodie)"
   386 
   485 
   387     |ex block|
   486     |ex block|
   388 
   487 
   389     ex := Exception new 
   488     ex := Exception new 
   390               signal:self
   489 	      signal:self
   391               parameter:nil
   490 	      parameter:nil
   392               errorString:something printString
   491 	      errorString:something printString
   393               suspendedContext:thisContext sender.
   492 	      suspendedContext:thisContext sender.
   394 
   493 
   395     ex resumeBlock:[:value | ^ value].
   494     ex resumeBlock:[:value | ^ value].
   396     self evaluateHandlerWith:ex.
   495     self evaluateHandlerWith:ex.
   397 
   496 
   398     (block := handlerBlock) isNil ifTrue:[
   497     (block := handlerBlock) isNil ifTrue:[
   399         "
   498 	"
   400          if I am not the NoHandlerSignal, raise it ...
   499 	 if I am not the NoHandlerSignal, raise it ...
   401          passing the exception as parameter.
   500 	 passing the exception as parameter.
   402         "
   501 	"
   403         self == NoHandlerSignal ifFalse:[
   502 	self == NoHandlerSignal ifFalse:[
   404             ^ NoHandlerSignal 
   503 	    ^ NoHandlerSignal 
   405                   raiseRequestWith:ex
   504 		  raiseRequestWith:ex
   406                        errorString:('unhandled exception: ' , ex errorString)
   505 		       errorString:('unhandled exception: ' , ex errorString)
   407         ].
   506 	].
   408 
   507 
   409         "
   508 	"
   410          otherwise,
   509 	 otherwise,
   411          take either a per-process emergencyHandlerBlock 
   510 	 take either a per-process emergencyHandlerBlock 
   412          or the global emergencyHandler (from Exception) ...
   511 	 or the global emergencyHandler (from Exception) ...
   413         "
   512 	"
   414         block := Processor activeProcess emergencySignalHandler.
   513 	Processor notNil ifTrue:[ 
   415         block isNil ifTrue:[
   514 	    "care for signal during startup (Processor not yet created)"
   416             block := Exception emergencyHandler
   515 	    block := Processor activeProcess emergencySignalHandler.
   417         ]
   516 	].
       
   517 	block isNil ifTrue:[
       
   518 	    block := Exception emergencyHandler
       
   519 	].
       
   520 	block isNil ifTrue:[
       
   521 	    "care for error during startup (Exception not yet initialized)"
       
   522 	    ^ MiniDebugger enterWithMessage:ex errorString
       
   523 	]
   418     ].
   524     ].
   419 
   525 
   420     "... and call it"
   526     "... and call it"
   421     ^ block value:ex.
   527     ^ block value:ex.
   422 !
   528 !
   427      The argument, aString is used as errorString."
   533      The argument, aString is used as errorString."
   428 
   534 
   429     |ex block|
   535     |ex block|
   430 
   536 
   431     ex := Exception new 
   537     ex := Exception new 
   432               signal:self
   538 	      signal:self
   433               parameter:aParameter 
   539 	      parameter:aParameter 
   434               errorString:aString
   540 	      errorString:aString
   435               suspendedContext:thisContext sender.
   541 	      suspendedContext:thisContext sender.
   436 
   542 
   437     ex resumeBlock:[:value | ^ value].
   543     ex resumeBlock:[:value | ^ value].
   438     self evaluateHandlerWith:ex.
   544     self evaluateHandlerWith:ex.
   439 
   545 
   440     (block := handlerBlock) isNil ifTrue:[
   546     (block := handlerBlock) isNil ifTrue:[
   441         "
   547 	"
   442          if I am not the NoHandlerSignal, raise it ...
   548 	 if I am not the NoHandlerSignal, raise it ...
   443          passing the exception as parameter.
   549 	 passing the exception as parameter.
   444         "
   550 	"
   445         self == NoHandlerSignal ifFalse:[
   551 	self == NoHandlerSignal ifFalse:[
   446             ^ NoHandlerSignal 
   552 	    ^ NoHandlerSignal 
   447                   raiseRequestWith:ex
   553 		  raiseRequestWith:ex
   448                        errorString:('unhandled exception: ' , ex errorString)
   554 		       errorString:('unhandled exception: ' , ex errorString)
   449         ].
   555 	].
   450 
   556 
   451         "
   557 	"
   452          otherwise,
   558 	 otherwise,
   453          take either a per-process emergencyHandlerBlock 
   559 	 take either a per-process emergencyHandlerBlock 
   454          or the global emergencyHandler (from Exception) ...
   560 	 or the global emergencyHandler (from Exception) ...
   455         "
   561 	"
   456         block := Processor activeProcess emergencySignalHandler.
   562 	Processor notNil ifTrue:[ 
   457         block isNil ifTrue:[
   563 	    "care for signal during startup (Processor not yet created)"
   458             block := Exception emergencyHandler
   564 	    block := Processor activeProcess emergencySignalHandler.
   459         ]
   565 	].
       
   566 	block isNil ifTrue:[
       
   567 	    block := Exception emergencyHandler
       
   568 	].
       
   569 	block isNil ifTrue:[
       
   570 	    "care for error during startup (Exception not yet initialized)"
       
   571 	    ^ MiniDebugger enterWithMessage:ex errorString
       
   572 	]
   460     ].
   573     ].
   461 
   574 
   462     "... and call it"
   575     "... and call it"
   463     ^ block value:ex.
   576     ^ block value:ex.
   464 ! !
   577 ! !
   465 
   578 
   466 !Signal methodsFor:'private'!
   579 !Signal methodsFor:'private'!
   467 
   580 
   468 evaluateHandlerWith:anException
   581 evaluateHandlerWith:ex
   469     "search through the context-calling chain for a 'handle:do:'-context 
   582     "search through the context-calling chain for a 'handle:do:'-context 
   470      to the receiver or a SignalSet which includes the receiver.
   583      to the receiver or a parent of the receiver or a SignalSet which includes 
       
   584      the receiver.
   471      If found, take its 2nd argument (the handler) and evaluate
   585      If found, take its 2nd argument (the handler) and evaluate
   472      it with the exception as argument.
   586      it with the exception as argument.
   473      If none found, just return."
   587      If none found, just return."
   474 
   588 
   475     |con|
   589     |con|
   476 
   590 
   477     con := thisContext.
   591     con := thisContext.
   478     con := con sender.
   592     con := con sender.
   479     con isRecursive ifTrue:[
   593     con isRecursive ifTrue:[
   480         "
   594 	"
   481          mhmh - an error while in a handler
   595 	 mhmh - an error while in a handler
   482          go immediately into the debugger.
   596 	"
   483         "
   597 	((self == RecursiveRaiseSignal)
   484         ^ self enterDebuggerWith:anException
   598 	or:[RecursiveRaiseSignal isNil]) ifTrue:[
   485                          message:'recursive signal raise'
   599 	    "
       
   600 	     ... either while handling RecursiveSignal
       
   601 	     or at startup when RecursiveSignal is not yet
       
   602 	     created -
       
   603 	     - go immediately into the debugger.
       
   604 	    "
       
   605 	    ^ self enterDebuggerWith:ex
       
   606 			     message:'recursive signal raise'
       
   607 	].
       
   608 	^ RecursiveRaiseSignal 
       
   609 	    raiseRequestWith:ex
       
   610 		 errorString:('recursive signal raise: ' , ex errorString)
   486     ].
   611     ].
   487 
   612 
   488     [con notNil] whileTrue:[
   613     [con notNil] whileTrue:[
   489         (con selector == #'handle:do:') ifTrue:[
   614 	(con selector == #'handle:do:') ifTrue:[
   490             "
   615 	    "
   491              if this is the Signal>>handle:do: context
   616 	     if this is the Signal>>handle:do: context
   492              or a SignalSet>>handle:do: context with self in it,
   617 	     or a SignalSet>>handle:do: context with self in it,
   493              call the handler
   618 	     call the handler
   494             "
   619 	    "
   495             ((con receiver == self) 
   620 	    (con receiver accepts:self) ifTrue:[
   496             or:[(con receiver isMemberOf:SignalSet) 
   621 		"call the handler"
   497                 and:[con receiver includes:self]]) ifTrue:[
   622 
   498                 "call the handler"
   623 		ex handlerContext:con.
   499 
   624 		self doCallHandler:(con args at:1) with:ex.
   500                 anException handlerContext:con.
   625 
   501                 self doCallHandler:(con args at:1) with:anException.
   626 		"if the handler rejects or falls through we arrive here"
   502 
   627 		"continue search for another handler"
   503                 "if the handler rejects or falls through we arrive here"
   628 	    ].
   504                 "continue search for another handler"
   629 	].
   505             ].
   630 	con := con sender
   506         ].
       
   507         con := con sender
       
   508     ].
   631     ].
   509 
   632 
   510     "
   633     "
   511      we arrive here, if either no handler was found, or none of the
   634      we arrive here, if either no handler was found, or none of the
   512      handlers did a return (i.e. every handler rejected or fell through).
   635      handlers did a return (i.e. every handler rejected or fell through).