[squeak-dev] Exception and defaultAction

Igor Stasenko siguctua at gmail.com
Thu Aug 7 16:36:38 UTC 2008


2008/8/7 stephane ducasse <stephane.ducasse at free.fr>:
> Lukas
>
> This was not the exact question. We were discussing to know who is really
> calling defaultAction (I know how the debugger
> is raised). The question is who is calling defaultAction when the stack is
> empty.
> Is it the VM or something else.
>
> Now in the image the only sender is
>
> UndefinedObject>>handleSignal: exception
>        "When no more handler (on:do:) context left in sender chain this gets
> called.  Return from signal with default action."
>
>        ^ exception resumeUnchecked: exception defaultAction
>
> Who is calling handleSignal:
>
> Exception>>pass
>        "Yield control to the enclosing exception action for the receiver."
>
>        handlerContext nextHandlerContext handleSignal: self
>
> Exception>>signal
>        "Ask ContextHandlers in the sender chain to handle this signal.  The
> default is to execute and return my defaultAction."
>
>        signalContext := thisContext contextTag.
>        ^ thisContext nextHandlerContext handleSignal: self
>
> ContextPart>>handleSignal: exception
>        "Sent to handler (on:do:) contexts only.  If my exception class
> (first arg) handles exception then execute my handle block (second arg),
> otherwise forward this message to the next handler context.  If none left,
> execute exception's defaultAction (see nil>>handleSignal:)."
>
>        | val |
>        (((self tempAt: 1) handles: exception) and: [self tempAt: 3])
> ifFalse: [
>                ^ self nextHandlerContext handleSignal: exception].
>
>        exception privHandlerContext: self contextTag.
>        self tempAt: 3 put: false.  "disable self while executing handle
> block"
>        val := [(self tempAt: 2) valueWithPossibleArgs: {exception}]
>                ensure: [self tempAt: 3 put: true].
>        self return: val.  "return from self if not otherwise directed in
> handle block"
>
> So it seems that this is signal and when handleSignal: arrives on nil then
> the default action is fetch.
>
> Can somebody with a VM knowledge validate my hypothesis?
>

The primitive, which sits in #findNextHandlerContextStarting which is
get called from #nextHandlerContext
Does following:

primitiveFindHandlerContext
	"Primitive. Search up the context stack for the next method context
marked for exception handling starting at the receiver. Return nil if
none found"
	| thisCntx nilOop |
	thisCntx := self popStack.
	nilOop := nilObj.

	[(self isHandlerMarked: thisCntx) ifTrue:[
			self push: thisCntx.
			^nil].
		thisCntx := self fetchPointer: SenderIndex ofObject: thisCntx.
		thisCntx = nilOop] whileFalse.

	^self push: nilObj
----

This primitive is done just for speed reasons. You can see, that if
primitive fails (not exists in VM), the method's code does exactly
same:

findNextHandlerContextStarting
	"Return the next handler marked context, returning nil if there is
none.  Search starts with self and proceeds up to nil."

	| ctx |
	<primitive: 197>
	ctx := self.
		[ctx isHandlerContext ifTrue:[^ctx].
		(ctx := ctx sender) == nil ] whileFalse.
	^nil


> Setf
>
>
>
>
>
> On Aug 6, 2008, at 2:55 PM, Lukas Renggli wrote:
>
>>> This is not easy to figure out since when a debugger gets opened, the
>>> part
>>> of the stack used to open it is discarded (how?).
>>
>> Error>>#defaultAction raises a new exception, the UnhandledError.
>> UnhandledError has an instance-variable to remember the original
>> exception.
>>
>> UnhandledError opens the debugger as part of the #defaultAction. The
>> debugger uses the stack-frame of the original exception to display at
>> the top level. That's why you don't see the handling code itself.
>>
>> Lukas
>>
>> --
>> Lukas Renggli
>> http://www.lukas-renggli.ch
>>
>>
>
>
>



-- 
Best regards,
Igor Stasenko AKA sig.



More information about the Squeak-dev mailing list